2013-10-04 24 views
10

我想知道如何在免費的情況下編寫f x = zip x (tail x)。所以我使用了免提程序,結果是f = ap zip tailap是Control.Monad的一個函數「ap zip tail」的表達方式如何工作

我不明白點自由定義是如何工作的。如果我能從類型的角度理解它,我希望我能弄明白。

import Control.Monad (ap) 
let f = ap zip tail 
let g = ap zip 
:info ap zip tail f g 
ap :: Monad m => m (a -> b) -> m a -> m b 
    -- Defined in `Control.Monad' 
zip :: [a] -> [b] -> [(a, b)] -- Defined in `GHC.List' 
tail :: [a] -> [a]  -- Defined in `GHC.List' 
f :: [b] -> [(b, b)] -- Defined at <interactive>:3:5 
g :: ([a] -> [b]) -> [a] -> [(a, b)] 
    -- Defined at <interactive>:4:5 

通過觀察表達ap zip tail我認爲是拉鍊的ap和尾部的第一個參數是ap第二個參數。

Monad m => m (a -> b) -> m a -> m b 
      \--------/ \---/ 
       zip  tail 

但是,這是不可能的,因爲類型ziptail比什麼功能ap需要完全不同的。即使考慮到名單是一種單一的。

+0

唯一能想到的是,ap類型中的'a'成爲zip類型的'[a] - > [b]'。如果是這樣的話,那麼統治(如果它是合適的話)統治這一點的規則通常是什麼? – user7610

+1

ghci說,類型是'ap zip tail :: Monad(( - >)[b])=> [b] - > [(b,b)]'......沒有太多的調查,我會說'Monad(( - >)[b])'是你想要閱讀的內容。我*認爲* http://learnyouahaskell.com/for-a-few-monads-more#reader可能會幫助你瞭解這裏發生了什麼。 –

+0

順便說一句,'拉鍊<*> tail'相當於和漂亮尋找 – jozefg

回答

11

所以ap的類型簽名是Monad m => m (a -> b) -> m a -> m b。您已將它作爲參數ziptail,我們來看看它們的類型簽名。

tail :: [a] -> [a] ~ (->) [a] [a]開始(這裏~是類型等於運算符),如果我們比較這類型與第二個參數的類型爲ap

(->) [x] [x] ~ m a 
((->) [x]) [x] ~ m a 

我們得到a ~ [x]m ~ ((->) [x]) ~ ((->) a)。我們已經可以看到我們所在的monad是(->) [x],而不是[]。如果我們替換一下就可以進入ap類型簽名,我們得到:

(((->) [x]) ([x] -> b)) -> (((->) [x]) [x]) -> (((->) [x]) b) 

因爲這不是很可讀,能更常寫爲

([x] -> ([x] -> b)) -> ([x] -> [x]) -> ([x] -> b) 
~ ([x] -> [x] -> b) -> ([x] -> [x]) -> ([x] -> b) 

類型的zip[x] -> [y] -> [(x, y)]。我們已經可以看到,這個排隊的第一個參數來ap其中

[x]   ~ [x] 
[y]   ~ [x] 
[(x, y)] ~ b 

這裏我列出的各類垂直,這樣就可以很容易地看到哪些類型的排隊。所以很明顯x ~ xy ~ x[(x, y)] ~ [(x, x)] ~ b,這樣我們就可以完成代b ~ [(x, x)]ap的類型簽名,並得到

([x] -> [x] -> [(x, x)]) -> ([x] -> [x]) -> ([x] -> [(x, x)]) 
-- zip      tail  (ap zip tail) 
--           ap zip tail u = zip u (tail u) 

我希望清除的東西了你。

編輯:正如評論danvaripointed out,單子(->) a有時也被稱爲讀者單子。

+5

可能值得一提的是( - >)是Reader-monad – dnaq

5

有兩個方面來理解這一點:

  1. 類型魔法
  2. 實施的信息流

首先,這幫助我理解了類型魔法

1) zip   : [a] → ([a] → [(a,a)]) 
2) tail   : [a] → [a] 
3) zip <*> tail : [a] → [(a,a)] 

4) <*> : Applicative f ⇒ f (p → q) → f p → f q 

在此情況下,對於<*>

5) f x = y → x 

。注意,在圖5,f是一種類型的構造。應用fx產生一個類型。另外,這裏=被重載以表示類型的等價。

y是目前一個佔位,在這種情況下,它是[a],這意味着

6) f x = [a] -> x 

使用如圖6所示,我們可以重寫1,2和3,如下所示:

7) zip   : f ([a] → [(a,a)]) 
8) tail   : f [a] 
9) zip <*> tail : f ([a] → [(a,a)]) → f [a] → f [(a,a)] 

所以,看着4,我們代替如下:

10) p = [a] 
11) q = [(a,a)] 
12) f x = [a] → x 

(重複6在這裏再次作爲12)

其次,信息流,即實際功能。這種情況很容易,它是爲Applicative instance of y →中的<*>定義,這與不同的標識符名稱,並使用中綴風格在這裏改寫明確:

13) g <*> h $ xs = g xs (h xs) 

代如下:

14) g = zip 
15) h = tail 

給出:

zip <*> tail $ xs  (Using 14 and 15) 
    == 
zip xs (tail xs)   (Using 13) 
相關問題