Restricting a monad to a type class
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开发者_如何学Go 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.
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.
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.
Check out Martin Erwig's library, PFP:
The PFP library is a collection of modules for Haskell that facilitates probabilistic functional programming, that is, programming with stochastic values. The probabilistic functional programming approach is based on a data type for representing distributions. A distribution represent the outcome of a probabilistic event as a collection of all possible values, tagged with their likelihood.
精彩评论