15

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.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
namin
  • 37,139
  • 8
  • 58
  • 74
  • I believe that you can do this with the `ConstraintKinds` language extension and the `ConstraintKinds` package, see [here](https://hackage.haskell.org/package/ConstraintKinds-1.3.0/docs/Control-ConstraintKinds-Monad.html) for a constrained monad, and [here](https://hackage.haskell.org/package/ConstraintKinds-1.3.0/docs/Control-ConstraintKinds-Functor.html#t:FunctorConstraint) the `FunctorConstraint`. – nh2 Apr 05 '15 at 18:27

3 Answers3

13

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
  • 37,139
  • 8
  • 58
  • 74
  • Is the "least disruptive" solution not just a particular case of free monad ? (I know that this solution has been published before the free monad craze). – mb14 Jul 30 '16 at 12:24
10

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
  • 15,923
  • 9
  • 67
  • 96
3

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.

stites
  • 4,903
  • 5
  • 32
  • 43
ja.
  • 4,245
  • 20
  • 22