Skip to content

Instantly share code, notes, and snippets.

@jvranish
Created May 2, 2012 17:28
Show Gist options
  • Save jvranish/2578479 to your computer and use it in GitHub Desktop.
Save jvranish/2578479 to your computer and use it in GitHub Desktop.
An experiment with mixing value level typeclasses and implicit parameters
{-# LANGUAGE Rank2Types
, RebindableSyntax
, ImplicitParams
, NoMonomorphismRestriction #-}
import Data.Maybe
import Data.Function
import Data.String
import Prelude (undefined, error, String, (++))
-- value-level Monad definition:
data MonadI m = MonadI {
_return :: forall a . a -> m a,
_bind :: forall a b . m a -> (a -> m b) -> m b }
-- Monad operators (for RebindableSyntax)
a >>= k = _bind ?useMonadI a k
a >> b = a >>= const b
return a = _return ?useMonadI a
fail = error "WAAT"
-- Monad instance for Maybe:
monad'Maybe :: MonadI Maybe
monad'Maybe = MonadI {
_return = Just,
_bind = \m f -> case m of
Nothing -> Nothing
Just x -> f x }
{-
Here is the interesting part:
-}
someAction :: Maybe String
someAction = Just "sadf"
someOtherAction :: Maybe String
someOtherAction = Just "asdf"
-- A small sprinkling of magic
doMaybe :: ((?useMonadI::MonadI Maybe) => m) -> m
doMaybe m = let ?useMonadI = monad'Maybe in m
-- _almost_ normal do notation
foo :: Maybe String
foo = doMaybe $ do
a <- someAction
b <- someOtherAction
return $ a ++ b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment