user519985
user519985

Reputation: 71

How best to catch missing let!, do!, return and return! in computation expressions in F#

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?

Upvotes: 2

Views: 213

Answers (1)

kvb
kvb

Reputation: 55195

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
}

Upvotes: 3

Related Questions