2017-09-25 73 views
1

我有以下從haskellbook代碼片段,顯示分步實施,變壓器如何單子是要解開:如何包裝它?

module OuterInner where 

    import Control.Monad.Trans.Except 
    import Control.Monad.Trans.Maybe 
    import Control.Monad.Trans.Reader 

    -- We only need to use return once 
    -- because it's one big Monad 
    embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int 
    embedded = return 1 

    maybeUnwrap :: ExceptT String (ReaderT() IO) (Maybe Int) 
    maybeUnwrap = runMaybeT embedded 

    -- Next 
    eitherUnwrap :: ReaderT() IO (Either String (Maybe Int)) 
    eitherUnwrap = runExceptT maybeUnwrap 

    -- Lastly 
    readerUnwrap ::() -> IO (Either String (Maybe Int)) 
    readerUnwrap = runReaderT eitherUnwrap 

有一個鍛鍊,我必須包裝再次一切:

embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int 
embedded = ??? (const (Right (Just 1))) 

我試過如下:

embedded' :: MaybeT (ExceptT String (ReaderT() IO)) Int 
embedded' = MaybeT (ExceptT (ReaderT (const (Right (Just 1))))) 

但是編譯器會抱怨:

D:\haskell\chapter26\src\OuterInner.hs:24:15: error: 
    * Couldn't match type `Either a0' with `IO' 
     Expected type: MaybeT (ExceptT String (ReaderT() IO)) Int 
     Actual type: MaybeT (ExceptT String (ReaderT() (Either a0))) Int 
    * In the expression: 
     MaybeT (ExceptT (ReaderT (const (Right (Just 1))))) 
     In an equation for embedded': 
      embedded' = MaybeT (ExceptT (ReaderT (const (Right (Just 1))))) 

D:\haskell\chapter26\src\OuterInner.hs:24:32: error: 
    * Couldn't match type `Maybe Integer' 
        with `Either String (Maybe Int)' 
     Expected type: ReaderT() (Either a0) (Either String (Maybe Int)) 
     Actual type: ReaderT() (Either a0) (Maybe Integer) 
    * In the first argument of `ExceptT', namely 
     `(ReaderT (const (Right (Just 1))))' 
     In the first argument of `MaybeT', namely 
     `(ExceptT (ReaderT (const (Right (Just 1)))))' 
     In the expression: 
     MaybeT (ExceptT (ReaderT (const (Right (Just 1))))) 
Failed, modules loaded: none. 

如何解決練習?

回答

5

GHC打出的洞延伸救援!它可以讓你在表達式的某個地方探索_,並讓GHC告訴你需要的類型。所以,讓我們開始

:t MaybeT (ExceptT (ReaderT (const _))) 

<interactive>:1:33: error: 
    * Found hole: _ :: m (Either e (Maybe a)) 

現在我們需要的ReaderT() (Either e (Maybe a))值。水暖_一遍又一遍,我們終於在價值

embedded = MaybeT (ExceptT (ReaderT (const (return (Right (Just 1)))))) 
+0

到達什麼意思'GHC輸入孔延伸到rescue'? –

+1

嚴。那麼,就像Chip&Dale一樣。來幫助你。 – arrowd

+0

在表達式中的任意位置放置一個_。根據規範它是一個無效的標識符,所以無論如何這將是一個錯誤。 GHC可以自由推斷其類型並在導致該錯誤之前打印該類型。你建立一個表達式並把_放在任何你不確定的地方,然後你可以把它放下來,讓這些類型編寫代碼。 – HTNW

5

您已經定義了MaybeT (ExceptT String (Reader())) Int。你錯過了最內層,IO。與其他人不同,IO沒有具體的表示,但您可以使用returnpure(duh)向其中注入純數值。

embedded' = MaybeT . ExceptT . ReaderT 
      $ (pure .) . const . Right $ Just 1