【问题标题】:"For all" statements in HaskellHaskell 中的“For all”语句
【发布时间】: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

但这不起作用。我认为因为thenelse 子句具有不同的类型,不幸的是你不能分段定义函数的(共)域。我该如何解决这个问题?

【问题讨论】:

  • 您想要的输出不会(不能)按原样进行类型检查。您可以将其更改为 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


【解决方案1】:

但这不起作用。我认为因为 then 和 else 子句有不同的类型,不幸的是你不能分段定义你的函数的(co)域。我该如何解决这个问题?

您的诊断是正确的; thenelse 必须具有相同的类型。严格来说,没有“解决这个问题”。无论您采用什么解决方案,都必须在条件的两个分支中使用相同的类型。一种方法是设计一种自定义数据类型,对您想要的可能性进行编码,然后改用它。像这样的东西会起作用:

-- | A 'Run' of @a@ is either 'One' @a@ 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 类型。

【讨论】:

  • 啊,是的。忘记了 Haskell 中的列表不能混合类型。
猜你喜欢
  • 2013-09-01
  • 2018-08-06
  • 1970-01-01
  • 2014-07-23
  • 2021-12-24
  • 2011-02-16
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
相关资源
最近更新 更多