[英]How does type unification/function application work at a high level in Haskell?
我覺得我並沒有真正了解函數應用程序是如何工作的,或者我可能正在關注一些我不應該做的事情。
讓我們嘗試確定(fmap .)
的類型簽名
fmap :: (x -> y) -> fx -> fy
(.) :: (b -> c) -> (a -> b) -> a -> c -- signatures taken from GHC
將fmap
應用於(.)
,我們本質上想讓(x -> y) -> fx -> fy
和(b -> c)
相等。 當我第一次嘗試這樣做時,我記得有一段非常艱難的時光。 您必須將一組 4 個變量與一組 2 個變量相匹配,所以顯然您必須進行一些分組,但是如何? 我看到了 3 種可能的解決方案,它們都有效嗎? 還是只有1? 我讀到編譯器並沒有真正考慮括號,所以我們最終得到x -> y -> fx -> fy
和b -> c
,還有與右邊相關的函數,所以fmap
實際上應該看起來像x -> (y -> (fx -> fy))
,這導致我
b = x
c = y -> fx -> fy
導致(a -> x) -> (a -> y -> fx -> fy)
作為(fmap .)
的簽名。
我已經看到解決這個問題的分組是(a -> b) -> (fa -> fb)
。 所以
b = x -> y
c = fx -> fy
導致(a -> x -> y) -> a -> fx -> fy
,這與 GHC 的(a1 -> a2 -> b) -> a1 -> f a2 -> fb
if 或多或少相同你重命名一些類型變量。
現在比較兩個結果,去掉括號:
a -> x -> a -> y -> fx -> fy
a -> x -> y -> a -> fx -> fy
我們可以清楚地看到第 3 和第 4 個參數類型是切換的,這意味着它們顯然不一樣,因為flip
是一個東西。 這意味着這個替換
b = x
c = y -> fx -> fy
無效。 還是我錯過了什么?
我有一種感覺,當我應該反過來做時,我正試圖根據簽名使函數工作。 :t fmap 'c'
失敗, Couldn't match expected type 'a -> b' with actual type 'Char'
這意味着您不能真正部分應用fmap
的a -> b
部分。 您只能部分應用fmap
本身,我猜它的第一個參數是不可分割的。 我不知道我是否得到了這一切背后的模式。
我真的應該嘗試編寫一個類型化的 lambda 演算。
我看到了 3 種可能的解決方案,它們都有效嗎?
不。
還是只有1?
只有一個。 (x -> y) -> fx -> fy
等於(x -> y) -> (fx -> fy)
並且僅是因為->
是右結合的。 把括號放在其他點是錯誤的。
我讀到編譯器並沒有真正考慮括號,
那是假的。 編譯器隱含地工作,因為括號總是以右關聯方式添加:類型a -> b -> c -> d
僅作為a -> (b -> (c -> d))
處理。 相比之下,類型(a -> b) -> c -> d
僅被處理為(a -> b) -> (c -> d)
,類型(a -> b -> c) -> d
僅作為(a -> (b -> c)) -> d
處理。
所以我們最終得到
x -> y -> fx -> fy
和b -> c
,
不,那是錯誤的,你必須保留括號。 我們必須滿足類型相等
(x -> y) -> (f x -> f y)
~
b -> c
唯一的解決方案是
b ~ (x -> y)
c ~ (f x -> f y)
正如你后來發現的那樣。
要了解統一中發生了什么,我認為如果您從以右關聯方式添加隱式括號開始是有益的。 如果你這樣做,你可以忘記像a -> b -> c
這樣的類型,而只關心基本情況(T -> U)
及其統一步驟:
from (T1 -> U1) ~ (T2 -> U2)
deduce T1 ~ T2 and U1 ~ U2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.