views:

324

answers:

3

In Haskell, is there a way to restrict a monad M a so that a satisfy a type class constraint?

I am translating the probabilistic modeling example from F# to Haskell. However, in Haskell, I omitted support because it would change data Distribution a to data (Ord a) => Distribution a. With this change, I get the following error:

...probabilisticModeling.hs:42:13:
    Could not deduce (Ord a) from the context ()
      arising from a use of `always'
                   at ...probabilisticModeling.hs:42:13-18
    Possible fix:
      add (Ord a) to the context of the type signature for `return'
    In the expression: always
    In the definition of `return': return = always
    In the instance declaration for `Monad Distribution'

Indeed, the type of always/return is: (Ord a) => a -> Distribution a. Is there a way I can have a monad Distribution, but force the constraint (Ord a) on this monad? I tried:

instance Monad Distribution where
    (>>=) = bind
    return :: (Ord a) => a -> Distribution a = always

But I get the error:

...probabilisticModeling2.hs:48:4:
    Pattern bindings (except simple variables) not allowed in instance declarations
      return :: (Ord a) => a -> Distribution a = always
Failed, modules loaded: none.

So it there a way to have a monad M a, but restrict the a with a constraint such as Ord a?

Thanks.

+3  A: 

My understanding of this is that you simply cannot, because a monad is meant to be generalized over all types, not some restricted subset of types such as (Ord a).

Instead of restricting the monadic type M a, you can simply restrict functions which use that monadic type, e.g.,

foo :: Ord a => Int -> M a

In fact, it is preferable to keep types as general as possible and use type classes only to restrict functions.

etc.

Gregory Higley
+2  A: 

It appears that I ran into a well-known problem in Haskell. I found many workarounds by googling for "restricted monads". This solutions seems to be the least disruptive. Still, for my purposes, it seems overkill. I think I'll keep the Distribution monad general, and simplify a support via a restricted function, as suggested by Revolucent.

namin
+1  A: 

Are you familiar with Martin Erwig's library:
http://web.engr.oregonstate.edu/~erwig/pfp/

ja
I stumbled upon it once. Thanks for reminding me.
namin