An FSharp monad TIL experience

Friday, May 20, 2016

I'm going about my business dealing with option types thinking I finally have a good handle on monad usage within F# when suddenly I receive the following error.

This expression was expected to have type 
    int
but here has type
    'a option

My first thought is that I've neglected to use let! but looking at my code the error is in a completely unexpected place.

type MaybeBuilder() =
  member this.Bind(m, f) = Option.bind f m
  member this.Return(x) = Some x

let maybe = new MaybeBuilder()

type SomeInt = {
    i : int
}

let foo =
  { i = maybe {
          let! x = Some(3) // <- error here
          let! y = None
          return x + y }
  }

That's very odd, because Some(3) is most certainly an 'a option and the let! should handle unwrapping for me.

Alas my connotation of the return keyword slipped back into the imperative context rather than the monadic context.

In the monadic sense, return wraps a value within the defined monad. It does not 'return the value'

What the compiler is really complaining about is that my SomeInt type has a property i that is an int, not an int option. The computation expression must result in a wrapped value.