[英]What are these explicit “forall”s doing?
這段代碼中forall
的目的是什么?
class Monad m where
(>>=) :: forall a b. m a -> (a -> m b) -> m b
(>>) :: forall a b. m a -> m b -> m b
-- Explicit for-alls so that we know what order to
-- give type arguments when desugaring
(省略了一些代碼)。 這來自Monads的代碼。
我的背景:我真的不了解forall
或Haskell隱含地擁有它們。
此外,它可能並不重要,但GHCi允許我在給出>>
a類型時省略forall
:
Prelude> :t (>>) :: Monad m => m a -> m b -> m b
(>>) :: Monad m => m a -> m b -> m b
:: (Monad m) => m a -> m b -> m b
(沒有錯誤)。
我的背景:我真的不了解forall或Haskell隱含地擁有它們。
好的,考慮id
的類型, a -> a
。 這是什么a
平均值,它從何而來? 定義值時,不能只使用未在任何位置定義的任意變量。 您需要頂級定義,函數參數或where
子句,&c。 通常,如果使用變量, 則必須將其綁定到某處。
類型變量也是如此, forall
是綁定類型變量的一種方式。 任何地方,你看到沒有明確的約束(例如,一個類型變量class Foo a where ...
結合a
,它隱含一個綁定的類定義中) forall
。
所以, id
的類型是隱含的forall a. a -> a
forall a. a -> a
。 這是什么意思? 幾乎就是這么說的。 我們可以得到一個類型a -> a
為所有可能的類型a
,或者從另一個角度來看,如果你選擇的任何特定類型,你可以得到代表“從你所選擇的類型函數本身”一類。 后面的措辭聽起來有點像定義一個函數,因此你可以認為forall
類似於lambda抽象類型。
GHC在編譯期間使用各種中間表示,並且它應用的一個轉換是使函數的相似性更直接:隱式forall
是明確的,並且在多態值用於特定類型的任何地方,它首先應用於類型爭論 。
我們甚至可以將forall
和lambdas都寫成一個表達式。 我會暫時濫用記譜法並替換forall a.
使用/\\a =>
以獲得視覺一致性。 在這種風格中,我們可以定義id = /\\a => \\(x::a) -> (x::a)
或類似的東西。 因此,代碼中的id True
的表達式最終將轉換為id Bool True
; 只是id True
不再有意義。
正如您可以重新排序函數參數一樣,您也可以重新排序類型參數,僅受限於類型參數必須在該類型的任何值參數之前出現的(相當明顯的)限制。 由於隱式forall
始終是最外層,因此GHC可能會在明確表示時選擇所需的任何順序。 一般情況下,這顯然無所謂。
我不確定在這種情況下到底發生了什么,但根據評論我會猜測,在某種意義上,使用顯式類型參數的轉換和do
notation的貶值是彼此不了解的,因此明確指定類型參數的順序以確保一致性。 畢竟,如果某些東西盲目地將兩個類型的參數應用於表達式,那么該表達式的類型是否為forall a b. ma -> mb -> mb
是很重要的forall a b. ma -> mb -> mb
forall a b. ma -> mb -> mb
或forall b a. ma -> mb -> mb
forall b a. ma -> mb -> mb
!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.