我正在阅读Scrap您的类型类.这为类型类提供了替代方案.但是,我被Paul Chiusano的评论所困扰,后者谈到恢复do notation语法.
坦率地说,我无法理解
return :: a -> (Monad f -> f a)
(>>=) :: (Monad f -> f a) -> (a -> (Monad f -> f b)) -> (Monad f -> f b)
Run Code Online (Sandbox Code Playgroud)
会帮助恢复做法
你可以像这样实现所有的monadic组合器,并且desugar可以为它们做记号.do块计算为接受monad字典的函数,因此您甚至可以方便地编写monad选择中的多态代码,而无需手动编写字典.
尤其是,它如何适合上述文章中提到的GADT风格方法的背景?
小智 6
Run Code Online (Sandbox Code Playgroud){-# LANGUAGE Rank2Types, RebindableSyntax #-} import qualified Prelude import qualified System.IO import Prelude (String, ($), (++)) import System.IO (IO)
加布里埃尔冈萨雷斯的建议
Run Code Online (Sandbox Code Playgroud)data MonadI f = MonadI { _return :: forall a . a -> f a, _bind :: forall a b . f a -> (a -> f b) -> f b }
您可以使用Paul Chiusano建议的类型实现必要的功能return,(>>=)如下所示:
Run Code Online (Sandbox Code Playgroud)return :: a -> (MonadI f -> f a) return x = \dict -> (_return dict) x (>>=) :: (MonadI f -> f a) -> (a -> (MonadI f -> f b)) -> (MonadI f -> f b) ma >>= f = \dict -> (_bind dict) (ma dict) (\x -> f x dict)
这还不足以恢复记号,因为你也需要(>>)和(遗憾地)fail.您可以按如下方式实现它们:
Run Code Online (Sandbox Code Playgroud)(>>) :: (MonadI f -> f a) -> (MonadI f -> f b) -> (MonadI f -> f b) ma >> mb = ma >>= (\_ -> mb) fail :: String -> MonadI f -> f a fail str = \_ -> Prelude.error str -- Because let's not further entertain that idea.
现在我们有了编写简单程序所需的工具:
Run Code Online (Sandbox Code Playgroud)main :: IO () main = (\m -> m monad'IO) $ do putStrLn "What is your name?" name <- getLine putStrLn $ "Hello, " ++ name
当然,我们将不得不借用一些东西System.IO:
Run Code Online (Sandbox Code Playgroud)getLine :: MonadI IO -> IO String getLine = \_ -> System.IO.getLine putStrLn :: String -> (MonadI IO -> IO ()) putStrLn str = \_ -> System.IO.putStrLn str monad'IO :: MonadI IO monad'IO = MonadI { _return = (Prelude.return :: a -> IO a), _bind = ((Prelude.>>=) :: IO a -> (a -> IO b) -> IO b) }
| 归档时间: |
|
| 查看次数: |
111 次 |
| 最近记录: |