2

I love computation expressions, but I make simple mistakes like forgetting the return keyword or the ! on expressions like let! and return!, or I simply forget to write the do!. This happens much with state monads where I tend to forget about the state and just focus on the monadic operators I have defined.

I sometimes make sure my monadic operators return a type that is "of monad type" instead of an "anonymous" function. This helps to track my forgetful typing, yet is not really ideal. Anybody have better tricks?

user519985
  • 71
  • 3
  • 1
    Encapsulating state inside a monad type (instead of passing around plain functions) is standard practice, partly because it avoids this kind of error. What don't you like about this approach? – Tim Robinson Dec 07 '10 at 16:41
  • Your are right, I said "not ideal" but maybe there is no other way to make things implicitly wrong as soon as possible. I think I "kind of" like the "naked" functional type signature of the state monad. Yet wrapping it up ok. Thanks. – user519985 Dec 07 '10 at 17:11

1 Answers1

3

Given a typical monad, your code shouldn't compile if you're missing a ! after a keyword because the types won't work out. For example:

let sum = async {
  let x = async { return 1 }
  let y = async { return 2 }
  return x + y
}

This won't compile because you're attempting to add two Async<int>s, but it will compile if you change the lets to let!s.

Similarly, to identify missing returns, just look out for compiler warning messages and odd monadic types:

let sum = async {
  let! x = async { return 1 }
  let! y = async { return 2 }
  x + y // warning FS0020
}

In this case, sum is an Async<unit>, which should be apparent when you try to use it elsewhere in your code. Alternatively, you can use a type annotation to catch this problem immediately:

let sum : Async<int> = async { // error FS0001: type mismatch
  let! x = async { return 1 }
  let! y = async { return 2 }
  x + y // warning FS0020
}
kvb
  • 54,864
  • 2
  • 91
  • 133
  • Correct, omissions lead to compiler errors. But with codes like a monadic parser, the error is not always obviously tied to the ommision. For example forgetting the ! on return!, returns well but not what you want. – user519985 Dec 07 '10 at 17:04
  • 1
    @user519985 - adding a type annotation should catch cases where you use `return` instead of `return!`. – kvb Dec 07 '10 at 17:55