Last active
December 18, 2018 22:12
-
-
Save ntreu14/38ce606c3212364c76312e63a418a107 to your computer and use it in GitHub Desktop.
Cons list in F#
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
namespace ConsList | |
module List = | |
type 'a List = | |
| Nil | |
| Cons of ('a * 'a List) | |
let private asCons v = Cons (v, Nil) | |
let rec map f = function | |
| Nil -> Nil | |
| Cons (v, rest) -> Cons (f v, map f rest) | |
let rec iter action = function | |
| Nil -> () | |
| Cons (v, rest) -> action v; iter action rest | |
let rec filter predicate = function | |
| Nil -> Nil | |
| Cons (v, rest) -> | |
if predicate v | |
then filter predicate <| Cons (v, rest) | |
else filter predicate rest | |
let rec fold folder state = function | |
| Nil -> state | |
| Cons (v, rest) -> fold folder (folder state v) rest | |
let rec append xs ys = | |
match xs with | |
| Nil -> ys | |
| Cons (v, rest) -> Cons (v, append rest ys) | |
let concat xs = xs |> fold append Nil | |
let collect f = concat << map f | |
let rec choose f = function | |
| Nil -> Nil | |
| Cons (v, rest) -> | |
match f v with | |
| Some x -> Cons (x, choose f rest) | |
| None -> choose f rest | |
let rec reverse = function | |
| Nil -> Nil | |
| Cons (v, rest) -> append (reverse rest) <| Cons (v, Nil) | |
let rec reduce reducer = function | |
| Nil -> invalidArg "[| |]" "Cannot pass in an empty array" | |
| Cons (head, rest) -> fold reducer head rest | |
let isEmpty = function | |
| Nil -> true | |
| _ -> false | |
let head = function | |
| Nil -> invalidArg "Nil" "Cannot get head of Nil." | |
| Cons (head, _) -> head | |
let tail = function | |
| Nil -> invalidArg "Nil" "Cannot get tail of Nil." | |
| Cons (_, rest) -> rest | |
let scan folder state = | |
fold | |
(fun a b -> append (folder (head a) b |> asCons) (tail a)) | |
(asCons state) | |
let inline sum list = reduce (+) list | |
let inline sumBy f = sum << map f | |
let exists predicate = | |
filter predicate >> isEmpty >> not | |
let contains x = | |
exists ((=) x) | |
let rec tryFind predicate = function | |
| Nil -> None | |
| Cons (v, rest) -> | |
if predicate v | |
then Some v | |
else tryFind predicate rest | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment