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
let NOT = function | 1 -> 0 | _ -> 1
let AND x y = match x,y with | (1,1) -> 1 | _ -> 0
let OR  x y = match x,y with | (0,0) -> 0 | _ -> 1
let XOR x y = match x,y with | (1,1) | (0,0) -> 0 | _ -> 1
let NAND x y = (x,y) ||> AND |> NOT
let NOR  x y = (x,y) ||> OR  |> NOT
let XNOR x y = (x,y) ||> XOR |> NOT

let HALFADDER x y = (x,y) ||> AND,(x,y) ||> XOR
let FULLADDER x y z =
  let c,s   = (x,y) ||> HALFADDER
  let c',s' = (z,s) ||> HALFADDER
  (c,c') ||> OR, s'

let itb n =
  System.Convert.ToString(0+n, 2).PadLeft(32,'0')
  |> Seq.map string |> Seq.map int |> Seq.toList

let bti (ls:int list) =
  ls |> List.map string |> List.reduce (+)
     |> fun x -> System.Convert.ToInt32(x,2)

let add x y =
  (x |> itb , y |> itb)
  ||> List.zip
  |> List.rev
  |> List.fold(
    fun (c,zs) (x,y) -> (x,y,c) |||> FULLADDER |> fun (c',z) -> c',z::zs) (0,[])
  |> fun (x,ys) -> ys |> bti

// Eight cases:
(0,0,0) |||> FULLADDER;;
(1,0,0) |||> FULLADDER;;
(0,1,0) |||> FULLADDER;;
(1,1,0) |||> FULLADDER;;
(0,0,1) |||> FULLADDER;;
(1,0,1) |||> FULLADDER;;
(0,1,1) |||> FULLADDER;;
(1,1,1) |||> FULLADDER;;

// Examples taken from 'Domino Addition - Numberphile'
(42,17) ||> add;;
(55,27) ||> add;

Code output:

val NOT : _arg1:int -> int
val AND : x:int -> y:int -> int
val OR : x:int -> y:int -> int
val XOR : x:int -> y:int -> int
val NAND : x:int -> y:int -> int
val NOR : x:int -> y:int -> int
val XNOR : x:int -> y:int -> int
val HALFADDER : x:int -> y:int -> int * int
val FULLADDER : x:int -> y:int -> z:int -> int * int
val itb : n:int -> int list
val bti : ls:int list -> int
val add : x:int -> y:int -> int

> val it : int * int = (0, 0)
> val it : int * int = (0, 1)
> val it : int * int = (0, 1)
> val it : int * int = (1, 0)
> val it : int * int = (0, 1)
> val it : int * int = (1, 0)
> val it : int * int = (1, 0)
> val it : int * int = (1, 1)

> val it : int = 59
> val it : int = 82

References: