【发布时间】:2016-01-23 13:48:03
【问题描述】:
我正在通过一些 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
但这不起作用。我认为因为then 和else 子句具有不同的类型,不幸的是你不能分段定义函数的(共)域。我该如何解决这个问题?
【问题讨论】:
-
您想要的输出不会(不能)按原样进行类型检查。您可以将其更改为 ADT,但原始代码要好得多。
-
像
[(1,2),(3,2)]这样的列表具有Num a => [(a,a)]类型。但是[(4,1),(3,2),3]只是不在haskell 中进行类型检查。 -
我投票结束这个问题,因为它似乎没有真正的答案,除了“你不能用静态类型语言做到这一点” (或者实际上“这就是静态类型的重点”)。请edit your question,如果你觉得你可以澄清你在问什么。
-
为什么要有这样的列表?告诉我们您将如何使用它,或许我们可以为您提供一些替代方案。
-
您需要一个包含两种值的类型,可以放入列表中。例如。
Either Int (Int,Int)或自定义代数类型。您需要将这两种值都包装在它们相关的构造函数中。
标签: haskell if-statement types type-conversion conditional