如果Haskell允許類型操作符 部分IMO,這將更容易理解。該類型
a -> b
是相當於
(->) a b
這樣就意味着
(->) a
相同
(a ->)
它本質上說,它的功能類型參數通過其 輸出類型。因此,這意味着,我們應該有
ret :: a -> (((->) r) a)
或等價
ret :: a -> ((r ->) a) -- Note that this is invalid Haskell, it's using our magical TypeOperatorSections extension
ret :: a -> (r -> a)
ret :: a -> r -> a
警告:破壞者AHEAD!
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
嗯,這種類型看起來很簡單和熟悉。如果我們看看它在Hoogle,在 第一個結果是
const :: a -> b -> a
和結果的其餘約seq
,par
,以及其他更先進的功能 ,我們可以相當肯定都不是我們」重新尋找。所以 const
是:
instance MyMonad ((->) r) where
return = const
對於flatMap
實施,我們可以通過註釋我們的論點 與它們的類型入手:
flatMap (m :: r -> a) (f :: a -> (r -> b)) = _
所以我們有一個功能,當給定r
回報a
,以及 給定的功能a
和r
返回b
,並且我們想要flatMap m f :: r -> b
。由於我們 有r
類型沒有參數,下面我們來介紹一個:
flatMap m f = \r -> _
如果你使用的輸入孔,GHC會告訴你,現在你需要b
類型的東西。相關的綁定是
m :: r -> a
f :: a -> r -> b
r :: r
只有一種方式來獲得a
,這是從m
,所以
flatMap m f = \r -> _ (m r)
現在我們已經GHC告訴我們,我們需要a -> b
類型的東西,與相關 綁定
f :: a -> r -> b
r :: r
這看起來非常簡單的對我說:
flatMap m f = \r -> f (m r) r
而我們的代碼類型檢查!現在有時間來測試它。期望的行爲是 我們相同的輸入參數傳遞給幾個功能在DO塊(你 可以使用RebindableSyntax
如果你真的想用做記號),所以像
test :: Int -> Int
test =
(*2) `flatMap` (\x1 ->
(^3) `flatMap` (\x2 ->
(7-) `flatMap` (\x3 ->
return (x1 * x2 + x3)
)
)
)
應該是相同的作爲
test' x = (2*x) * (x^3) + (7-x)
而對於我們的實現,它確實工作:
> test 5 == test' 5
True
> test 100 == test' 100
True
首先,你需要了解參數類型:所以如果我寫'data Foo x = ...'我有一個類型的家族,我們可以稱之爲「抽象類型」Foo。 (官方的描述是'Foo'是一種類型'* - > *',所以放入任何類型的'*'都會給出一種'*'類型)。如果你明白這一點,那麼'( - >)a'是一種類型'* - > *',就像'Foo'是我們指定數據Foo x = ...'時一樣。它是以「a」作爲參數的抽象類型的函數。 – 2014-12-11 15:57:38