Skip to content

Instantly share code, notes, and snippets.

@pirrmann
Forked from akimboyko/Nat.fs
Last active December 25, 2015 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pirrmann/7046590 to your computer and use it in GitHub Desktop.
Save pirrmann/7046590 to your computer and use it in GitHub Desktop.
An implementation of basic non-negative integers, based on https://gist.github.com/akimboyko/7019648, but rewritten in a more F# idiomatic way
//An implementation of basic non-negative integers, based on https://gist.github.com/akimboyko/7019648,
//but rewritten in a more F# idiomatic way
module Naturals
open System
type Natural =
| Zero
| Succ of Natural
member x.IsZero' = x = Zero
member x.Predecessor = match x with | Succ p -> p | _ -> raise (ArithmeticException())
member x.Plus(y) =
match y with
| Zero -> x
| Succ y' -> (Succ x).Plus(y')
member x.Minus(y) =
match x, y with
| _, Zero -> x
| Zero, _ -> raise (ArithmeticException())
| Succ x', Succ y' -> x'.Minus(y')
override x.ToString() =
match x with
| Zero -> "0"
| Succ(y) -> y.ToString() + "+"
//Same test as the source Gist, but with MsTest as a runner
module NatTests
open Microsoft.VisualStudio.TestTools.UnitTesting
open FsUnit.MsTest
open Naturals
[<TestClass>]
type BreafastTests() =
[<TestMethod>]
let ``Zero has IsZero true`` () =
Zero.IsZero' |> should be True
[<TestMethod>]
let ``Successor has IsZero false`` () =
let successorOfZero = Succ(Zero)
successorOfZero.IsZero' |> should be False
[<TestMethod>]
let ``Zero has no predecessor`` () =
(fun () -> Zero.Predecessor) |>
should throw typeof<System.ArithmeticException>
[<TestMethod>]
let ``Zero has successor other then Zero`` () =
Succ( Zero) |> should not' (be sameAs Zero)
[<TestMethod>]
let ``First natural number has successor other then itself`` () =
let firstNaturalNumber = Succ(Zero)
Succ(firstNaturalNumber) |> should not' (sameAs firstNaturalNumber)
[<TestMethod>]
let ``Predecessor for first natural number is Zero``() =
let firstNaturalNumber = Succ(Zero)
firstNaturalNumber.Predecessor |> should be (sameAs Zero)
[<TestMethod>]
let ``Predecessor for 2 is 1``() =
let nat1 = Succ(Zero)
let nat2 = Succ(nat1)
nat2.Predecessor |> should be (sameAs nat1)
[<TestMethod>]
let ``Zero to return string interpretation "0"``() =
Zero.ToString() |> should equal "0"
[<TestMethod>]
let ``Two to return string interpretation "0++"``() =
let nat2 = Succ(Succ(Zero))
nat2.ToString() |> should equal "0++"
[<TestMethod>]
let ``Zero plus Zero should be Zero``() =
Zero.Plus(Zero) |> should be (sameAs Zero)
[<TestMethod>]
let ``Zero plus non-Zero should be non-Zero itself``() =
let nat1 = Succ(Zero)
let nat2 = Succ(nat1)
Zero.Plus(nat2) |> should be (sameAs nat2)
[<TestMethod>]
let ``Zero minus Zero should be Zero``() =
Zero.Minus(Zero) |> should be (sameAs Zero)
[<TestMethod>]
let ``Zero minus non-Zero should raise ArithmeticException``() =
let nat2 = Succ(Succ(Zero))
(fun () -> Zero.Minus(nat2)) |>
should throw typeof<System.ArithmeticException>
[<TestMethod>]
let ``Two plus Zero should be Two``() =
let one = Succ(Zero)
let two = Succ(one)
two.Plus(Zero) |> should be (sameAs two)
[<TestMethod>]
let ``One plus Two should be Three``() =
let one = Succ(Zero)
let two = Succ(one)
let three = Succ(two)
one.Plus(two).ToString() |> should equal (three.ToString())
[<TestMethod>]
let ``Two minus Zero should be Two``() =
let one = Succ(Zero)
let two = Succ(one)
two.Minus(Zero) |> should be (sameAs two)
[<TestMethod>]
let ``Three minus One should be Two``() =
let one = Succ(Zero)
let two = Succ(one)
let three = Succ(two)
three.Minus(one).ToString() |> should equal (two.ToString())
[<TestMethod>]
let ``Two minus Three should raise ArithmeticException``() =
let one = Succ(Zero)
let two = Succ(one)
let three = Succ(two)
(fun () -> two.Minus(three)) |>
should throw typeof<System.ArithmeticException>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment