[英]How do I find out the type of a haskell expression without ghci?
我很擅長推斷lambda表達式的類型,只要它沒有任何奇怪的函數,例如map
, filter
, foldr
或其中的任何組合即可。 但是,一旦我有類似
\x y -> map x (y (. x))
我完全迷路了,無法終生解決不使用ghci的類型。
任何幫助將非常感激
謝謝
我認為“怪異”是指高階函數。 該表達式包含兩個: map :: (a -> b) -> [a] -> [b]
和(.) :: (b -> c) -> (a -> b) -> a -> c
。 它也是一個lambda,因此本身可能是一個高階函數。 此處帶括號的箭頭是函數參數的類型。
map
顯示y
必須返回x
接受作為參數的項目列表。 因此,它們具有部分簽名x :: _yitem -> _outeritem
和y :: _yarg -> [_yitem]
,其中此map
的返回值為[_outeritem]
類型。 請注意,我們尚不知道這些通配符中可以容納多少個箭頭。
(. x)
轉換為\\l -> l . x
\\l -> l . x
轉換為\\lr -> l (xr)
。 整個lambda是適合y
的參數,因此y
是一個高階函數。 l
必須接受x
的返回值。 那有個名字,所以l :: _outeritem -> _lret
和(. x) :: (_outeritem -> _lret) -> _xarg -> _lret
l :: _outeritem -> _lret
(. x) :: (_outeritem -> _lret) -> _xarg -> _lret
,因為r
用作x
的參數。 哦,因為地圖是_yitem
所以_xarg
是已知的。
好的,這本身就是一堆令人困惑的步驟,因此讓我們整理一下結果:
type OuterLambda = _xtype -> _ytype -> MapRet
x :: _yitem -> _outeritem
type MapRet = [_outeritem]
y :: YArg -> [_yitem]
type YArg = (_outeritem -> _lret) -> _yitem -> _lret
y :: ((_outeritem -> _lret) -> _yitem -> _lret) -> [_yitem]
進展! 它具有往返x
和y
每種類型的名稱。 但是我們的表達是lambda,因此我們必須接受這兩個:
(_yitem -> _outeritem) ->
(((_outeritem -> _lret) -> _yitem -> _lret) -> [_yitem]) ->
[_outeritem]
那是一種很長的類型。 讓我們將其與山本雄二向我們展示的編譯器推斷類型進行比較:
(a0 -> b0) ->
(((b0 -> c0) -> a0 -> c0) -> [a0]) ->
[b0]
它匹配。 在這里,我們有很多功能函數:表達式期望函數x
和y
,而y
期望函數本身具有l
函數。 而且,我們確實為之命名的所有類型可能反過來變得非常復雜。
故意注釋錯誤的類型(通常()
)將對您有所幫助。
例如:
> (\x y -> map x (y (. x))) :: ()
<interactive>:1:2: error:
• Couldn't match expected type ‘()’
with actual type ‘(a0 -> b0)
-> (((b0 -> c0) -> a0 -> c0) -> [a0]) -> [b0]’
• The lambda expression ‘\ x y -> map x (y (. x))’
has two arguments,
but its type ‘()’ has none
In the expression: (\ x y -> map x (y (. x))) :: ()
In an equation for ‘it’: it = (\ x y -> map x (y (. x))) :: ()
這篇文章介紹了這個技巧: http : //www.parsonsmatt.org/2018/05/19/ghcid_for_the_win.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.