Reputation: 15819
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
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