簡體   English   中英

類型為(num-> num)-> num的Haskell函數

[英]Haskell function with type (num -> num) -> num

我在R.Bird的函數式編程書中的一個練習中苦苦掙扎,該書要求提供類型為(num-> num)-> num的函數的示例

我能想到的最好的是多態類型

func1 f = f 3
:t func1
func1 :: Num t1 => (t1 -> t2) -> t2

我遇到的問題是我無法指定f的返回類型,因此該類型仍為(num-> t2)-> t2。

我試圖強制返回f的類型如下:

square x = x * x
:t func1 square
func1 square :: Num t2 => t2 -> t2

當然,如果我嘗試查找func1∘square的類型,它將只是num-> num

如果足以提供可以分配該類型的功能 ,那么您的功能就足夠了。 也就是說,以下類型檢查就可以了:

func1 :: Num a => (a -> a) -> a
func1 f = f 3

另一方面,如果您想要一個推斷為具有該類型的函數,則需要進行一些技巧。 我們要在此處指定f 3的結果和我們輸入的3的類型相同。 強制兩個術語具有相同類型的標准方法是使用asTypeOf ,它是通過以下方式實現的:

asTypeOf :: a -> a -> a
asTypeOf x _ = x

因此,讓我們嘗試:

> :t \f -> f 3 `asTypeOf` 3
(Num a, Num t) => (t -> a) -> a

不幸的是對於我們來說,這是行不通的,因為3f 3和獨立3被推斷為使用的潛在不同實例Num 不過,它比\\f -> f 3還要近一些-注意新的Num a我們之前沒有的輸出約束。 一個明顯的下一個想法是let一個可變-bind至3和重用該變量作為參數既fasTypeOf ; 那么GHC肯定會得到f的參數和結果具有相同類型的圖片,對嗎?

> :t \f -> let x = 3 in f x `asTypeOf` x
(Num a, Num t) => (t -> a) -> a

討厭鬼。 事實證明, let進行所謂的“讓一般化”。 x將與3一樣多態,並且可以在不同的使用地點專門用於不同的類型。 通常這是一個不錯的功能,但是由於我們進行的是不自然的運動,因此我們需要做不自然的事情...

好吧,下一個想法:一些lambda演算不包含let ,並且當您需要一個let a = b in c ,您可以寫(\\a -> c) b而不是let a = b in c中寫let a = b in c (\\a -> c) b 這對我們來說是特別有趣,因為Haskell使用特殊限制的多態的,這意味着這里面c的類型, a單態 所以:

> :t \f -> (\x -> f x `asTypeOf` x) 3
Num a => (a -> a) -> a

現在,您抱怨asTypeOf在作弊,因為它使用的類型聲明與其推斷的類型不匹配,並且整個練習的重點是僅通過推斷獲得正確的類型。 (如果我們可以使用與推斷的類型不匹配的類型聲明,則可以在func1 :: Num a => (a -> a) -> a; func1 f = f 3處停下來func1 :: Num a => (a -> a) -> a; func1 f = f 3好的,沒問題:還有另一種標准的方法可以強制兩個表達式的類型統一,即將它們放在一個列表中。 所以:

> :t \f -> (\x -> head [f x, x]) 3
Num a => (a -> a) -> a

ew,現在我們終於可以在原則上從頭開始構建無需任何類型聲明即可獲取正確類型的術語所需的所有工具。

func1 f = let x = fx in x這是一個分函數,從技術上講,它具有所需的類型,您應了解它們的含義以及它們在haskell中的工作方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM