[英]Haskell taking in two list with a int and returning a tuple
我正在嘗試學習 Haskell 並看到了一個練習,上面寫着
編寫兩個具有相同類型的不同 Haskell 函數:
[a] -> [b] -> Int -> (a,b)
所以根據我的理解,表達式應該包含兩個列表,一個 int 並返回一個列表類型的元組。
到目前為止我嘗試過的是
together :: [a] -> [b] -> Int -> (a,b)
together [] [] 0 = (0,0)
together [b] [a] x = if x == a | b then (b,a) else (0,0)
我知道我走了很遠,但任何幫助表示贊賞!
首先,您需要確定函數應該返回什么。 這部分是由簽名決定的。 但是您仍然可以想出許多返回不同內容但具有相同簽名的函數。
這里最直接的函數之一可能是返回放置在由第三個參數確定的索引上的元素。
返回(0,0)
沒有意義,因為a
和b
本身不是數字類型。 此外, if x == a | b
if x == a | b
在語義上無效。 你可以把它寫成x == a || x == b
x == a || x == b
,但這不起作用,因為a
和b
本身不是Int
s。
我們可以實現一個函數,在索引為0
情況下返回兩個列表的頭部。 如果索引為負,或者兩個列表中的至少一個被用盡,那么我們可以引發錯誤。 我將其作為練習,以防索引大於0
該怎么做:
together :: [a] -> [b] -> Int -> (a,b)
together [] _ = error "List exhausted"
together _ [] = error "List exhausted"
together (a:_) (b:_) 0 = (a, b)
together (a:_) (b:_) n | n < 0 = error "Negative index!"
| …
因此,您仍然需要填寫…
。
我通常不喜歡那些“用這個簽名編寫任何函數”類型的練習,正是因為它們是多么隨意。 您應該找出一個對該特定簽名有意義的定義並實施它。 在很多情況下,您可以通過忽略盡可能多的參數來改變它:
fa :: [a] -> [b] -> Int -> (a,b)
fa (a:_) (b:_) _ = (a,b)
fa _ _ _ = error "Unfortunately, this function can't be made total because lists can be empty"
這里的錯誤是需要注意的重要一點。 您試圖通過返回0
來解決該問題,但這僅在0
是a
和b
類型的有效值時才有效。 您的下一個想法可能是某種“默認”值,但並非每種類型都有這樣的概念。 關鍵的觀察是,在沒有關於類型的任何知識的情況下,為了從函數生成值,您需要首先從其他地方獲取該值*。
如果您確實想要一個更合理的定義,則需要考慮該Int
參數的用途; 也許它是每個列表中的第 n 個元素? 在take :: Int -> [a] -> [a]
和head :: [a] -> a
這應該可以作為練習。
同樣,您將x
與a
進行比較的想法不適用於所有類型; 並非每種類型都可以與Int
。 您可能認為這會使泛型函數受到極大限制; 這就是您通常了解如何表達對您獲得的類型的某些期望的地方,這將允許您僅對所有可能類型的某些子集進行操作。
*這也是id :: a -> a
只有一種可能實現的原因。
編寫兩個具有相同類型的不同 Haskell 函數:
[a] -> [b] -> Int -> (a,b)
正如 Willem 和 Bartek 指出的那樣,有很多具有這種類型的亂碼函數。
Bartek 采取了根據該類型最簡單的函數的外觀來選擇兩個的方法。 一個是除了拋出錯誤之外什么都不做的函數。 一個是選擇每個列表的第一個元素,希望它們不是空的,否則就會失敗。 這是一種有點理論化的方法,因為您可能永遠不想在實踐中使用這些函數。
Willem 采取了建議使用該類型的實際有用函數的方法,並繼續探索如何窮盡此類函數的可能模式:對於列表,匹配空列表[]
和非空列表a:_
,對於整數, 匹配一些停止點, 0
和一些類別n < 0
and …
。
我想到的一個問題是,是否還有其他具有這種類型簽名的同樣有用的函數,或者是否必須假設構造第二個函數。 Int
參數與[a]
和[b]
中元素的位置有某種關系似乎很自然,因為它們也是整數,特別是因為返回了一對單一的(a,b)
。
但是我能想到的唯一遠程有用的函數(在不完全愚蠢的意義上)是這個的小變化:例如, Int
可能是從末尾而不是從頭開始的位置,或者如果沒有足夠的其中一個列表中的元素,它可以默認為列表的最后一個元素而不是錯誤。 這些都不是很令人愉快(“從最后”與可能無限的列表沖突,並且回退到列表的最后一個元素與列表不一定具有最后一個元素的事實相沖突) ,因此很容易采用 Bartek 編寫最簡單的無用函數作為第二個函數的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.