Haskell 恢复do表示法语法

Haskell 恢复do表示法语法,haskell,Haskell,我在通读。这为类型类提供了一个替代方案。然而,我被一条关于恢复do表示法语法的评论困住了 坦率地说,我不明白怎么做 return :: a -> (Monad f -> f a) (>>=) :: (Monad f -> f a) -> (a -> (Monad f -> f b)) -> (Monad f -> f b) 有助于恢复do符号 你可以像这样实现所有的一元组合,还有desugar 对他们做记号。do块的计算结果为接受

我在通读。这为类型类提供了一个替代方案。然而,我被一条关于恢复do表示法语法的评论困住了

坦率地说,我不明白怎么做

return :: a -> (Monad f -> f a) 
(>>=) :: (Monad f -> f a) -> (a -> (Monad f -> f b)) -> (Monad f -> f b)
有助于恢复do符号

你可以像这样实现所有的一元组合,还有desugar 对他们做记号。do块的计算结果为接受 monad字典,因此您甚至可以方便地编写 多态性在单子的选择上,无需线程 手动查找字典

特别是,它将如何适应上述文章中提到的GADT风格的方法

根据加布里埃尔·冈萨雷斯的建议

您可以使用Paul Chiusano建议的类型,按如下方式实现必要的函数
return
(>>=)

这还不足以恢复do表示法,因为您还需要
(>>)
和()
fail
。您可以按如下方式实现它们:

现在我们有了编写简单程序所需的设施:

{-# LANGUAGE Rank2Types, RebindableSyntax #-}

import qualified Prelude
import qualified System.IO
import Prelude (String, ($), (++))
import System.IO (IO)
data MonadI f = MonadI {
    _return :: forall a . a -> f a,
    _bind :: forall a b . f a -> (a -> f b) -> f b
}
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)
(>>) :: (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.
main :: IO ()
main = (\m -> m monad'IO) $ do
    putStrLn "What is your name?"
    name <- getLine
    putStrLn $ "Hello, " ++ name
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)
}