-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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() + "+" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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