2015-10-29 4 views
9

Ich las Scrap your type classes. Dies bietet eine Alternative für Typklassen. Ich war jedoch mit einem Kommentar von Paul Chiusano fest, die über die Wiederherstellung der Do Notation Syntax sprach.Wiederherstellen der Do Notation Syntax

Ehrlich gesagt konnte ich nicht verstehen, wie

return :: a -> (Monad f -> f a) 
(>>=) :: (Monad f -> f a) -> (a -> (Monad f -> f b)) -> (Monad f -> f b) 

helfen Notation tun würde erholen

Sie können alle monadischen combinators wie dies umzusetzen, und desugar ihnen Notation tun. Der Do-Block wertet eine Funktion aus, die das Monad-Wörterbuch akzeptiert, so dass Sie sogar bequem Code schreiben können, der in der Wahl von monad polymorph ist, ohne das Wörterbuch manuell herumführen zu müssen.

Und vor allem, wie es in den Kontext der GADT-Stil-Ansatz im obigen Artikel erwähnt würde passen?

Antwort

6
{-# LANGUAGE Rank2Types, RebindableSyntax #-} 

import qualified Prelude 
import qualified System.IO 
import Prelude (String, ($), (++)) 
import System.IO (IO) 

Mit Gabriel Gonzales' Vorschlag

data MonadI f = MonadI { 
    _return :: forall a . a -> f a, 
    _bind :: forall a b . f a -> (a -> f b) -> f b 
} 

Sie die notwendigen Funktionen implementieren könnte return und (>>=) wie folgt, mit der Art, wie von Paul Chiusano vorgeschlagen:

Dies ist nicht genug tun-Notation zu erholen, weil Sie auch (>>) benötigen und (sadly) fail. Sie können sie wie folgt implementieren:

(>>) :: (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. 

Und jetzt haben wir die erforderlichen Einrichtungen einfache Programme schreiben:

main :: IO() 
main = (\m -> m monad'IO) $ do 
    putStrLn "What is your name?" 
    name <- getLine 
    putStrLn $ "Hello, " ++ name 

Natürlich sind wir gehen zu müssen einige Dinge aus System.IO dafür zu leihen:

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) 
} 
Verwandte Themen