[Haskell-cafe] AT solution: rebinding >>= for restricted monads

David Roundy droundy at darcs.net
Sun Dec 17 22:00:29 EST 2006

I've now almost got a FD solution to this problem, except that it won't
work, and I don't know why.  Of course, it's possible that the AT solution
won't work either (I'm still compiling ghc, should have it in the
morning...), but at least it seems far simpler.  My FD solution is below.
My trouble is that I really don't understand the limitations on FDs, which
as I understand it is why Simon P.J. opposes adding them to Haskell':
they're hard to understand.

This all seems to work (although you'll see that I was reduced to using
unsafeCoerce# in the IO instance, which is embarrassing--to say the
least--but not unsafe), until I hit the RealWitness instance at the bottom,
at which point ghc bombs out with:

    Couldn't match expected type `m'' (a rigid variable)
           against inferred type `RealWitness a a''
      `m'' is bound by the type signature for `>>' at Witness.hs:11:29
    When using functional dependencies to combine
      Witness WitnessReally a b (RealWitness a b),
(and a screenful more)

Any suggestions?

{-# OPTIONS -fno-implicit-prelude -fglasgow-exts #-}

module Witness ( Witness ) where

import GHC.Exts (unsafeCoerce#)
import Prelude hiding ( (>>), (>>=), return, fail )
import qualified Prelude as P ( (>>), (>>=), return, fail )

class Witness w a b m | w a b -> m, m -> w a b where
    (>>=) :: (Witness w a a' m', Witness w a' b m'') => m' x -> (x -> m'' y) -> m y
    (>>) ::  (Witness w a a' m', Witness w a' b m'') => m' x -> m'' y -> m y
    f >> g = f >>= const g
    private_return :: x -> m x
    fail :: String -> m x

return :: Witness w a a m => x -> m x
return = private_return

data WitnessIO

instance Witness WitnessIO () () IO where
    private_return = P.return
    fail = P.fail
    f >>= g = x2io f P.>>= y2io g
        where x2io :: Witness WitnessIO a b m => m x -> IO x
              x2io = unsafeCoerce#
              y2io :: Witness WitnessIO a b m => (y -> m x) -> (y -> IO x)
              y2io = unsafeCoerce#

data RealWitness a b c -- this would be concrete
data WitnessReally

instance Witness WitnessReally a b (RealWitness a b) where

The following monad is what I'd like to define if I could use associated type synonyms:

class Witness w where
    type W w a b
    (>>=) :: W w a b x -> (x -> W w b c y) -> W w a c y
    (>>) :: W w a b x -> W w b c y -> W w a c y
    f >> g = f >>= const g
    return :: x -> W w a a x
    fail :: String -> W w a b x

instance Monad m => Witness m where
    W m a b = m
    (>>=) = Prelude.(>>=)
    (>>) = Prelude.(>>)
    return = Prelude.return
    fail = Prelude.fail

More information about the Haskell-Cafe mailing list