6

I've been toying with monads in F# (aka computation expressions) and I wrote this simple Identity monad:

type Identity<'a> = 
    | Identity of 'a

type IdentityBuilder() =
    member x.Bind (Identity v) f  = f(v)
    member x.Return v = Identity v
let identity = new IdentityBuilder()

let getInt() = identity { return Int32.Parse(Console.ReadLine()) }

let calcs() = identity {
    let! a = getInt()    // <- I get an error here
    let! b = getInt()
    return a + b }

I don't understand the error I'm getting in the marked line:

This expression was expected to have type Identity<'a> but here has type 'b * 'c

I think this makes no sense as getInt() is clearly a value of type Identity<'a>.

Can anyone tell me what am I doing wrong?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510

2 Answers2

9

The computation expression syntax wants Bind to have a tupled, not curried argument. So

member x.Bind((Identity v), f) = f(v)

See this article for all signatures.

Dario
  • 48,658
  • 8
  • 97
  • 130
  • 1
    Or see section 6.4.10 of the language spec: http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html – Brian Dec 16 '09 at 21:00
  • 1
    Note to self: revise that wiki page because it makes no sense ;) – Juliet Dec 17 '09 at 03:53
3

The problem is the type of your Bind function - it shouldn't take curried arguments. If you change it to:

member x.Bind (Identity v, f)  = f(v)

then it should work.

kvb
  • 54,864
  • 2
  • 91
  • 133