Haskell的新手。爲什麼下面的代碼不是工作?我該如何連接尾部和頭部?爲什麼'tail x:head x'不起作用?
func :: [String] -> [String]
func x = tail x:head x
Haskell的新手。爲什麼下面的代碼不是工作?我該如何連接尾部和頭部?爲什麼'tail x:head x'不起作用?
func :: [String] -> [String]
func x = tail x:head x
讓我們通過工種理解爲什麼我們專注於正確的在此之前沒有工作解。
您呈現:
func :: [String] -> [String]
func x = tail x:head x
我們知道:
tail x :: [String]
head x :: String
(:) :: String -> [String] -> [String]
^ ^the 'head' argument's position
^---the 'tail' argument's position
所以很明顯的類型不匹配了 - 其中元素有望列表並在列表預計的元素。
值得注意的是,沒有任何默認的snoc
運算符,哪個cons是元素到列表的末尾。你可以通過(++) :: [String] -> [String] -> [String]
追加到列表中。由於head xs
不是[String]
,我們可以通過方括號將其設爲一個:[head xs]
。
此外,使用head
和tail
並不安全 - 如果列表爲空,它們將引發異常。最好使用模式匹配,這樣編譯器除了可以更明顯地看到部分函數外,還可以警告你。在這種情況下,我們會第一個元素和列表的其餘部分匹配:
func (firstElement : restOfList) = restOfList ++ [firstElement]
而且看這應該是顯而易見的func
還沒有空列表定義,因此我們可以添加更多的情況:
func [] = []
解決方案:
變化
func :: [String] -> [String]
func x = tail x:head x
到
func :: [String] -> [String]
func x = tail x++[head x]
這將不起作用,因爲'tail x:[head x]'仍然是一個類型錯誤。 –
@DietrichEpp編輯。 –
你可能也想要一個空的列表大小寫,因爲似乎沒有必要讓這個函數在一個空列表上失敗。 – duplode
':'並不意味着「連接」。它具體採用單個元素(左側)和列表(右側)並生成新列表。 – melpomene
@melpomene我明白了。那麼你如何建議我恰當地連接這個? –
我建議像'func(x:xs)= xs ++ [x]''。請注意,'++'在左邊參數的長度上是線性的,所以你可能不想在循環中做這個。 – melpomene