Skip to content

Instantly share code, notes, and snippets.

@ntreu14
Last active November 15, 2019 18:21
Show Gist options
  • Save ntreu14/f3e416ecc2e2ebd15c46abad27f14a12 to your computer and use it in GitHub Desktop.
Save ntreu14/f3e416ecc2e2ebd15c46abad27f14a12 to your computer and use it in GitHub Desktop.
Implementation of `NonEmpty` in F# with `map`, `concat` and `bind`.
type 'a NonEmpty = NonEmpty of 'a * 'a list
let inline (&|) head tail = NonEmpty (head, tail)
let inline (|&|) head = NonEmpty (head, [])
let toList = function NonEmpty (head, xs) -> head :: xs
let mapNonEmpty f = function
NonEmpty (head, xs) -> NonEmpty (f head, List.map f xs)
let bindNonEmpty (f: 'a -> 'b NonEmpty) = function
| NonEmpty (head, xs) ->
match f head with
| NonEmpty (b, bs) ->
let bs' = xs |> List.collect (f >> toList)
b &| (List.append bs bs')
let concatNonEmpty = function
| NonEmpty (NonEmpty (head, rest), remaining) ->
NonEmpty (head, List.append rest <| List.collect toList remaining)
let bindNonEmpty' (f: 'a -> 'b NonEmpty) =
mapNonEmpty f >> concatNonEmpty
let example = 1 &| [2]
let addOne = (+) 1
let nextTwo i = i + 1 &| [i + 2]
[
mapNonEmpty addOne
bindNonEmpty nextTwo
bindNonEmpty' nextTwo
]
|> List.iter (fun f -> f example |> printfn "%A")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment