Utils Code Snippet 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 //  You  can  disable  this  warning  by  using  ' -- mlcompatibility'  or  ' -- nowarn : 62 
# nowarn  "62"  
module  Util  = 
    open  System 
    
    let  iso8601  :  int  ->  int  ->  int  ->  string  = 
        fun  y  m  d  ->  ( new  DateTime ( y , m , d )) . ToString ( "o" )  +  "Z" 
    
    let  byteToHex  :  byte  ->  string  = 
        fun  b  ->  b . ToString ( "x2" ) 
        
    let  bytesToHex  :  byte  array  ->  string  = 
        fun  bytes  ->  bytes  |>  Array . fold  ( fun  a  x  ->  a  +  ( byteToHex  x ))  "" 
    
    let  utf8ToBytes  :  string  ->  byte  array  = 
        fun  utf8  ->  System . Text . Encoding . UTF8 . GetBytes  utf8 
    
    let  sha256'  :  byte  array  ->  byte  array  = 
        fun  bytes  -> 
            use  sha256  =  System . Security . Cryptography . SHA256 . Create () 
            sha256 . ComputeHash ( buffer  =  bytes ) 
    
    (* mon@razerRamon:~$ echo -n 'foo' | sha256sum
       2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae  - *) 
    let  sha256  :  string  ->  string  = 
        fun  utf8  ->  utf8  |>  ( utf8ToBytes  >>  sha256'  >>  bytesToHex ) 
    
    let  ceilPow  :  uint64  ->  uint64  = 
        fun  n  -> 
            let  rec  loop  :  ( uint64  *  int )  ->  uint64  =  function 
                |  0 UL ,  acc  ->  1  <<<  acc  |>  uint64 
                |  m   ,  acc  -> 
                    let  m'  =  m  &&&  1 UL 
                    ( m - m'  >>>  1 ,  acc + 1 )  |>  loop 
            ( n - 1 UL , 0 )  |>  loop 
 
Utils Code output: 
> 
module Util = begin
  val iso8601 : y:int -> m:int -> d:int -> string
  val byteToHex : b:byte -> string
  val bytesToHex : bytes:byte array -> string
  val utf8ToBytes : utf8:string -> byte array
  val sha256' : bytes:byte array -> byte array
  val sha256 : utf8:string -> string
  val ceilPow : n:uint64 -> uint64
end 
JSON Code Snippet 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 module  Json  = 
    (* http://json.org/ *) 
    type  value  = 
        |  String   of  string 
        |  Number   of  float 
        |  Object   of  ( string  *  value )  list 
        |  Array    of  value  list 
        |  Boolean  of  bool 
        |  Null 
    with 
        override  json . ToString ()  = 
            let  rec  print  :  value  ->  string  =  function 
                |  String   s   ->  sprintf  " \" %s \" "  s 
                |  Number   n   ->  sprintf  "%f"  n 
                |  Object   xs  ->  xs  |>  objectHelper 
                |  Array    xs  ->  xs  |>  arrayHelper 
                |  Boolean  b   ->  sprintf  "%b"  b 
                |  Null        ->  "null" 
            and  objectHelper  :  ( string  *  value )  list  ->  string  = 
                function 
                |  []  ->  "{ }" 
                |  xs  -> 
                    sprintf  "{ %s }" 
                      ( xs 
                       |>  List . map  ( fun  ( name , value )  -> 
                            sprintf  "%s: %s" 
                                ( String  name  |>  print )  ( value  |>  print )) 
                       |>  List . reduce  ( fun  x  y  ->  sprintf  "%s, %s"  x  y )) 
            and  arrayHelper  :  value  list  ->  string  =  function 
                |  []  ->  "[ ]" 
                |  xs  -> 
                    sprintf  "[ %s ]" 
                      ( xs 
                       |>  List . map  print 
                       |>  List . reduce  ( fun  x  y  ->  sprintf  "%s, %s"  x  y )) 
            
            json  |>  print 
 
JSON Code output: 
> 
module Json = begin
  type value =
    | String of string
    | Number of float
    | Object of (string * value) list
    | Array of value list
    | Boolean of bool
    | Null
    with
      override ToString : unit -> string
    end
end 
Merkle Code Snippet 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 module  Merkle  = 
    open  Util 
    
    type  hash   =  string 
    type  json   =  string 
    type  count  =  uint64 
    
    type  tree  = 
        private 
        |  Leaf    of  json  option 
        |  Branch  of  ( hash  *  count )  *  tree  *  tree 
    with 
        override  tree . ToString ()  = 
            let  rec  print  :  ( int  *  tree )  ->  string  =  function 
                |  i ,  Leaf   None  ->  
                    sprintf  " \n %s NIL"  ( String . replicate  i  " \t " ) 
                |  i ,  Leaf  ( Some  json )  -> 
                    sprintf  " \n %s json: %s"  ( String . replicate  i  " \t " )  json 
                |  i ,  Branch  (( h , n ) , left , right )  -> 
                    sprintf  " \n %s * hash:  %s"  ( String . replicate  i  " \t " )  h  + 
                    sprintf  " \n %s * count: %i"  ( String . replicate  i  " \t " )  n  + 
                    sprintf  " \n %s   - left: %s" 
                        ( String . replicate  i  " \t " )  (( i + 2 , left )   |>  print )  + 
                    sprintf  " \n %s   - right: %s" 
                        ( String . replicate  i  " \t " )  (( i + 2 , right )  |>  print ) 
            ( 0 , tree )  |>  print 
    
    module  Tree  = 
        let  init    :  json  ->  tree  = 
            fun  msg  -> 
                let  h  =  msg  |>  Util . sha256 
                Branch (( h ,  1 UL ) ,  msg  |>  Some  |>  Leaf ,  Leaf  None ) 
        let  insert  :  json  ->  tree  ->  tree  = 
            fun  msg  tree  -> 
                let  helper  :  tree  ->  hash  option  =  function 
                    |  Leaf   None         ->  None 
                    |  Leaf  ( Some  msg )    ->  msg  |>  Util . sha256  |>  Some 
                    |  Branch (( h ,_ ) ,_,_ )  ->  h    |>  Some 
                
                let  rec  loop  :  tree  ->  tree   =  function 
                    |  Leaf   None          ->  msg  |>  Some  |>  Leaf 
                    |  Leaf  ( Some  x )  as  l  -> 
                        let  h1  =  x        |>  Util . sha256 
                        let  h2  =  msg      |>  Util . sha256 
                        let  h   =  h1  +  h2  |>  Util . sha256 
                        
                        Branch (( h , 2 UL ) ,  l ,  msg  |>  Some  |>  Leaf ) 
                        
                    |  Branch (( h , n ) , l , r )  as  b  -> 
                        match  n  >  1 UL  &&  n  =  ( n  |>  ceilPow )  with 
                            |  true   -> 
                                let  h'  =  h  +  ( msg  |>  Util . sha256 )  |>  Util . sha256 
                                Branch (( h' , n + 1 UL ) ,  b ,  msg  |>  Some  |>  Leaf ) 
                            |  false  -> 
                                let  rt  =  r   |>  loop 
                        
                                let  lh  =  l   |>  helper 
                                let  rh  =  rt  |>  helper 
                        
                                let  h'  =  ( lh , rh )  |>  function 
                                    |  None    ,  None     ->  h 
                                    |  Some  v  ,  None 
                                    |  None    ,  Some  v   ->  v 
                                    |  Some  h1 ,  Some  h2  ->  h1  +  h2  |>  Util . sha256 
                                
                                Branch (( h' , n + 1 UL ) ,  l ,  rt ) 
                
                tree  |>  loop 
 
Merkle Code output: 
> 
module Merkle = begin
  type hash = string
  type json = string
  type count = uint64
  type tree =
    private | Leaf of json option
            | Branch of (hash * count) * tree * tree
    with
      override ToString : unit -> string
    end
  module Tree = begin
    val init : msg:json -> tree
    val insert : msg:json -> tree:tree -> tree
  end
end 
Example, see References: 
                              +------------- 6 -------------+ 
                              |                             |
                    +-------- 4 --------+         +-------- 2 --------+
                    |                   |         |                   |
               +--- 2 ---+         +--- 2 ---+   'e'                 'f'
               |         |         |         |
              'a'       'b'       'c'       'd' 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 let  a , b , c , d , e  = 
    Json . Object [ 
        "name" ,  Json . String  "Bridge Cafe" 
        "rating" ,  Json . Number  4 . 
        "date" ,  Util . iso8601  2014  02  20  |>  Json . String 
        ] 
    ,  Json . Object [ 
        "name" ,  Json . String  "Prima Doner" 
        "rating" ,  Json . Number  2 . 
        "date" ,  Util . iso8601  2014  04  15  |>  Json . String 
        ] 
    ,  Json . Object [ 
        "name" ,  Json . String  "The Bull" 
        "rating" ,  Json . Number  3 . 
        "date" ,  Util . iso8601  2014  06  05  |>  Json . String 
        ] 
    ,  Json . Object [ 
        "name" ,  Json . String  "The Tall Ship" 
        "rating" ,  Json . Number  5 . 
        "date" ,  Util . iso8601  2014  10  30  |>  Json . String 
        ] 
    ,  Json . Object [ 
        "name" ,  Json . String  "Roy's Rolls" 
        "rating" ,  Json . Number  3 . 
        "date" ,  Util . iso8601  2015  01  10  |>  Json . String 
        ] 
let  f  = 
    Json . Object [ 
        "name" ,  Json . String  "Prima Doner" 
        "rating" ,  Json . Number  4 . 
        "date" ,  Util . iso8601  2015  02  12  |>  Json . String 
        ] 
let  mtree  = 
    (  Merkle . Tree . init  ( a  |>  string ) ,  [ b ; c ; d ; e ]  ) 
    ||>  List . fold  ( fun  a  x  ->  a  |>  Merkle . Tree . insert  ( x  |>  string )) 
let  mtree'  = 
    mtree 
    |>  Merkle . Tree . insert  ( f  |>  string ) 
 
> 
val e : Json.value =
  Object
    [("name", String "Roy's Rolls"); ("rating", Number 3.0);
     ("date", String "2015-01-10T00:00:00.0000000Z")]
val d : Json.value =
  Object
    [("name", String "The Tall Ship"); ("rating", Number 5.0);
     ("date", String "2014-10-30T00:00:00.0000000Z")]
val c : Json.value =
  Object
    [("name", String "The Bull"); ("rating", Number 3.0);
     ("date", String "2014-06-05T00:00:00.0000000Z")]
val b : Json.value =
  Object
    [("name", String "Prima Doner"); ("rating", Number 2.0);
     ("date", String "2014-04-15T00:00:00.0000000Z")]
val a : Json.value =
  Object
    [("name", String "Bridge Cafe"); ("rating", Number 4.0);
     ("date", String "2014-02-20T00:00:00.0000000Z")]
> 
val f : Json.value =
  Object
    [("name", String "Prima Doner"); ("rating", Number 4.0);
     ("date", String "2015-02-12T00:00:00.0000000Z")]
> 
val mtree : Merkle.tree =
  
 * hash:  dc999d3a9b252bebd171775e24668293e0ec1691f8d60331e85eed24ec6ca392
 * count: 5
   - left: 
     * hash:  1ae6f3cb6407d42c9be994971b46de89b6b5facb53e7d1a01c04a92f74264483
     * count: 4
       - left: 
         * hash:  28ee16e42affeecfc1b997487e4294f5067ced3bef2ca7c6324dcf86b7961954
         * count: 2
           - left: 
             json: { "name": "Bridge Cafe", "rating": 4.000000, "date": "2014-02-20T00:00:00.0000000Z" }
           - right: 
             json: { "name": "Prima Doner", "rating": 2.000000, "date": "2014-04-15T00:00:00.0000000Z" }
       - right: 
         * hash:  255a0ad108003e34e449159a63306a292357fd0d40f6449f148467ec2532ed0c
         * count: 2
           - left: 
             json: { "name": "The Bull", "rating": 3.000000, "date": "2014-06-05T00:00:00.0000000Z" }
           - right: 
             json: { "name": "The Tall Ship", "rating": 5.000000, "date": "2014-10-30T00:00:00.0000000Z" }
   - right: 
     json: { "name": "Roy's Rolls", "rating": 3.000000, "date": "2015-01-10T00:00:00.0000000Z" }
> 
val mtree' : Merkle.tree =
  
 * hash:  fb8b96a10235da8cc444a0ddf41bdcfef035f743e84d69b15b146c1af48c6848
 * count: 6
   - left: 
     * hash:  1ae6f3cb6407d42c9be994971b46de89b6b5facb53e7d1a01c04a92f74264483
     * count: 4
       - left: 
         * hash:  28ee16e42affeecfc1b997487e4294f5067ced3bef2ca7c6324dcf86b7961954
         * count: 2
           - left: 
             json: { "name": "Bridge Cafe", "rating": 4.000000, "date": "2014-02-20T00:00:00.0000000Z" }
           - right: 
             json: { "name": "Prima Doner", "rating": 2.000000, "date": "2014-04-15T00:00:00.0000000Z" }
       - right: 
         * hash:  255a0ad108003e34e449159a63306a292357fd0d40f6449f148467ec2532ed0c
         * count: 2
           - left: 
             json: { "name": "The Bull", "rating": 3.000000, "date": "2014-06-05T00:00:00.0000000Z" }
           - right: 
             json: { "name": "The Tall Ship", "rating": 5.000000, "date": "2014-10-30T00:00:00.0000000Z" }
   - right: 
     * hash:  dae71b4d5d4f57af9abd8cbf2a621e6d1eb110bef0ed34d0a0356e5dc766eff7
     * count: 2
       - left: 
         json: { "name": "Roy's Rolls", "rating": 3.000000, "date": "2015-01-10T00:00:00.0000000Z" }
       - right: 
         json: { "name": "Prima Doner", "rating": 4.000000, "date": "2015-02-12T00:00:00.0000000Z" } 
UnitTest for SHA256 
mon@razerRamon:~$ echo -n '{ "name": "Bridge Cafe", "rating": 4.000000, "date":
"2014-02-20T00:00:00.0000000Z" }' | sha256sum
b07cd889093179c2923fa8bfc480bfa153fe74c0b7009c46b33045d1e2d5632b -
mon@razerRamon:~$ echo -n '{ "name": "Prima Doner", "rating": 2.000000, "date":
"2014-04-15T00:00:00.0000000Z" }' | sha256sum
32128e3d309816c07db4ff4c995aa692c3390b48d23f6ac7429538b57dc2c372 -
mon@razerRamon:~$ echo -n
'b07cd889093179c2923fa8bfc480bfa153fe74c0b7009c46b33045d1e2d5632b
32128e3d309816c07db4ff4c995aa692c3390b48d23f6ac7429538b57dc2c372' | sha256sum
28ee16e42affeecfc1b997487e4294f5067ced3bef2ca7c6324dcf86b7961954 - 
1
2
3
4
5
6
7
8
9
10
 let  unitTest  = 
    let  a'  = 
        a  |>  string 
          |>  Util . sha256 
    let  b'  = 
        b  |>  string 
          |>  Util . sha256 
    "28ee16e42affeecfc1b997487e4294f5067ced3bef2ca7c6324dcf86b7961954" 
        =  (( a'  +  b' )  |>  Util . sha256 ) 
 
> 
val unitTest : bool = true 
References: 
  Technology at GDS’s Blog: