Callum Rogers
Callum Rogers

Reputation: 15819

Using fsharp-typeclasses to make a function that works on arbitrary monads

I'm trying to implement composM from the paper A pattern for almost compositional functions which accepts an arbitray monad and works on it. In Haskell the code would be:

data Expr =
    | Var String
    | Abs String Expr

composExprM :: (Monad m) => (Expr -> m Expr) -> Expr -> m Expr
composExprM f e =
    case e of
        Abs n e -> f e >>= (\e' -> return $ Abs n e')
        _       -> return e

I tried using fsharp-typeclasses with the code below:

type Expr =
    | Var of string
    | Abs of string * Expr

let rec composExprM f e = match e with
    | Abs (n, e) -> f e >>= (fun e' -> return' <| Abs (n, e'))
    | Var _      -> return' e

But I get type inference errors:

> Could not resolve the ambiguity inherent in the use of the operator 'instance' at or near this program point. Consider using type annotations to resolve the ambiguity.

> Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'instance'. The available overloads are shown below (or in the Error List window). Consider adding further type constraints

> Possible overload: 'static member Return.instance : _Monad:Return * Maybe<'a> -> ('a -> Maybe<'a>)'. Type constraint mismatch. The type 
      obj    
  is not compatible with type
    Maybe<'a>    
  The type 'obj' is not compatible with the type 'Maybe<'a>'.

> etc.....

Is what I'm trying to achieve possible with fsharp-typeclasses? Or do I have to restrict the function to only use a specific monad?

Upvotes: 2

Views: 248

Answers (1)

Gus
Gus

Reputation: 26174

Keep in mind that polymorphic functions using this technique should be inline, that's where the "magic" resides.

So, just add the inline keyword after let rec and it will compile.

Please let me know if the function behaves as expected. I will have a look at that paper later.

In the samples you will find many functions defined to work with any Monad. That was the main motivation when I started this project.

Upvotes: 3

Related Questions