Rebind用无类型类monad表示

cou*_*ech 2 monads haskell typeclass do-notation

可以重新绑定(>> =)并使用显式字典传递返回monad,如下所示:

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}

module Lib where

import Prelude hiding ((>>=), return)

data MonadDict m = MonadDict {
  bind :: forall a b. m a -> (a -> m b) -> m b ,
  ret :: forall a. a -> m a }

(>>=) :: (MonadDict m -> m a) -> (a -> (MonadDict m -> m b)) -> (MonadDict m -> m b)
return :: a -> (MonadDict m -> m a)

monadDictIO :: MonadDict IO

usage = let
  monadicCode = do
    ln <- const getLine 
    const . putStrLn $ ln
  in monadicCode monadDictIO
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法,如何表示monad,这样可以避免在每次使用monadic动作时忽略MonadDictmonad实例参数(使用const)?

fre*_*yle 6

你可以这样做:

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE RecordWildCards #-}

module Lib where
import Prelude hiding(return, fail, (>>=), (>>))

data MonadDict m = MonadDict
    { (>>=)  :: forall a b. m a -> (a -> m b) -> m b
    , (>>)   :: forall a b. m a -> m b -> m b
    , return :: forall a. a -> m a
    , fail   :: forall a. String -> m a
    }

monadDictIO :: MonadDict IO
monadDictIO = ...

foo :: MonadDict m -> String -> m ()
foo = ...

usage = let
    monadicCode m@MonadDict{..} = do
        ln <- getLine
        putStrLn ln
        foo m ln
    in monadicCode monadDictIO
Run Code Online (Sandbox Code Playgroud)