2015-10-23 36 views
0
聲明

我建立舒適通過一些Haskell的玩具問題去,我已經寫了下面的代碼斑點「對於所有」哈斯克爾

multipOf :: [a] -> (Int, a) 
multipOf x = (length x, head x) 
gmcompress x = (map multipOf).group $ x 

成功地瓶坯以下操作

gmcompress [1,1,1,1,2,2,2,3] = [(4,1),(3,2),(1,3)] 

現在我想要這個函數,而不是告訴我該集合中的一個元素具有多重性1,只是讓它獨立。所以要給出結果[(4,1),(3,2),3]代替。如果對於所有重數爲1的元素有一種說法(無論是在將列表變爲一對之後還是之後),將其作爲一個元素留下,其他,配對。我最初的,天真的想法是做以下事情。

multipOf :: [a] -> (Int, a) 
multipOf x = if length x = 1 then head x else (length x, head x) 
gmcompress x = (map multipOf).group $ x 

但是這是行不通的。我認爲,因爲thenelse子句有不同的類型,不幸的是,您不能逐段定義函數的(共)域。我該如何解決這個問題?

+4

您所需的輸出沒有(不能)按原樣鍵入檢查。您可以將其更改爲ADT,但原始代碼更好。 – Mephy

+1

類似'[(1,2),(3,2)]''的列表的類型爲'Num a => [(a,a)]''。但是'[(4,1),(3,2),3]'不會在haskell中進行類型檢查。 – Michael

+1

我投票結束這個問題,因爲它似乎並沒有_answer_,除了「你不能用靜態類型語言來做到這一點」(或者事實上「這就是靜態類型的要點」)。請[編輯你的問題](http://stackoverflow.com/posts/33312250/edit)如果你覺得你可以澄清你問的問題。 –

回答

3

但是這是行不通的。我認爲,因爲then和else子句有不同的類型,所以不幸的是,您無法逐個定義函數的(共)域。我該如何解決這個問題?

您的診斷是正確的; thenelse必須具有相同的類型。嚴格來說,沒有「越過這個問題」。無論您採用哪種解決方案,都必須在條件的兩個分支中使用相同的類型。一種方法是設計一個自定義數據類型來編碼您想要的可能性,然後使用它。像這樣的東西會工作:

-- | A 'Run' of @[email protected] is either 'One' @[email protected] or 'Many' of them (with the number 
-- as an argument to the 'Many' constructor). 
data Run a = One a | Many Int a 

但是要告訴你實話,我不認爲這會真的讓你得到任何東西。我會堅持(Int, a)編碼,而不是去這個Run類型。

+0

啊,是的。忘記Haskell中的列表不能混合類型。 – Tshimanga