2015-10-14 63 views
1

我正在閱讀紙張應用編程效果來自Conor McBride和Ross Paterson,我無法弄清楚爲什麼他們的第一段代碼是typechecks。 (我有很強的OCaml背景和弱的haskell背景)。它爲什麼會檢查和如何?

有一個功能apControl.Monad有以下類型:

ap :: Monad m => m (a -> b) -> m a -> m b 

此功能可以很容易地這樣寫的:

ap mf mx = do { f <- mf ; x <- mx ; return (f x) } 

然後,他們寫:

sequence :: [IO a] → IO [a] 
sequence [] = return [] 
sequence (c : cs) = return (:) `ap` c `ap` sequence cs 

我的問題是,我不知道如何制定0的類型,因爲(:)的類型與m (a -> b)無關,因爲它是a -> ([a] -> [a])

ap (Just (:))的類型是Maybe a -> (Maybe ([a] -> [a]))正如預期的那樣,但類型檢測器告訴我,ap (:)的類型是(a -> [a]) -> a -> [a]。這怎麼可能?

回答

7

如果你正在寫

return (:) `ap` c `ap` sequence cs 

然後,用明確的括號,這是

((return (:)) `ap` c) `ap` (sequence cs) 

所以,

(:)       :: a -> [a] -> [a] 
return (:)     :: IO (a -> [a] -> [a]) 
c        :: IO a 
(return (:)) `ap` c   :: IO ([a] -> [a]) 
sequence cs     :: IO [a] 
((return (:)) `ap` c) `ap` cs :: IO [a] 

關於第二個問題,ap (:)使用的單子實例其中

-- Monad instance for ((->) a) 
return x = \_ -> x 
x >>= f = \y -> f (x y) y 

所以,你必須:

ap :: (a -> (b -> c)) -> (a -> b) -> (a -> c) 
ap f g = \x -> f x (g x) 

如果你只是看了看ap的DO-塊定義並擴大了定義。

很可能現在這個第二個問題可能不會太重要或者不重要;專注於現在的第一個答案:)

+0

感謝您的解釋,並指出Monad實例( - >)a'它消除了魔法。 –

相關問題