【问题标题】:How to return different types in the same function in haskell?如何在haskell的同一个函数中返回不同的类型?
【发布时间】:2021-01-11 06:10:18
【问题描述】:

我不明白为什么,虽然我已经声明了数据类型,但函数不接受不同的返回。我也尝试创建一个“Result”类型,但还不足以解决问题。

看看我的代码:

type Set a = [a]
type Bag a = [(a, Int)]
type Seq a = [a]

data ComposedType a = Set a | Bag [a] | Seq a deriving(Eq, Show)
data ComposedResult a = Res1 [a] | Res2 [(a, Int)]

-- This function get a list [a] and returns a list of tuples [(a, Int)]
occrs :: (Ord a) => [a] -> [(a, Int)]
occrs [] = []
occrs xs = toList (fromListWith (+) [(x, 1) | x <- xs])

--getElements :: ComposedType a -> ComposedResult a
getElements (Set a) = (Set (nub a))
getElements (Seq a) = (Seq (sort a))
getElements (Bag a) = (Bag (occrs a))

错误:

  • 无法将类型 ([a], Int) 与“[a]”匹配 预期类型:ComposedType [a] 实际类型:ComposedType ([a], Int)
  • 在表达式中:(Bag (occrs a)) 在“getElements”的等式中: getElements (Bag a) = (Bag (occrs a))

【问题讨论】:

  • 请注意set使用a,这意味着第一行需要ComposeType [a],而不是ComposeType a,与@987654326相同@。但现在Bag 需要b ~ (a, Int),因此出现错误。
  • 您将Set 用作类型别名和构造函数名称。这两个用途是不相关的:类型定义data ComposedType a = Set a | Bag [a] | Seq a 根本不使用类型Set aBagSeq 同上。这可能不是您想要的。
  • 您认为type Set a = [a] 中的Setdata ComposedType a = Set a | ... 中的Set 相互关联吗?如果是这样,那可能是您混淆的核心部分——它们是相同的名称,但在两个不同的名称空间中(前者的类型名称空间和后者的计算名称空间)——可能值得添加一个答案讨论这个。

标签: haskell


【解决方案1】:

这不起作用的原因是因为 Set (num a) 例如具有类型 ComposedType [a],而对于 Bag (occrs),它将需要 ComposedTYpe (a, Int),因为与其他数据构造函数相比,Bag 使用as 的列表:[a]

如果您使用ComposedResult,那么您将需要使用Res1Res2 数据构造函数:

getElements :: (Eq a, Ord a) => ComposedType [a] -> ComposedResult a
getElements (Set b) = Res1 (nub b)
getElements (Seq b) = Res1 (sort b)
getElements (Bag b) = Res2 (occrs b)

但这将仍然不起作用。实际上Bag a 有一个参数b,但是b 的类型是[[a]],尽管occrs 可以使用列表列表(因为如果元素是,这些也是Ord 的一个实例ord 的一个实例,这意味着occrs b 的类型为[([a], Int)],而其他的(nub bsort b)的类型为[a],这样会再次引发麻烦。

我们可以通过将b 的元素连接在一起来解决这个问题:

getElements :: (Eq a, Ord a) => ComposedType [a] -> ComposedResult a
getElements (Set b) = Res1 (nub b)
getElements (Seq b) = Res1 (sort b)
getElements (Bag bs) = Res2 (occrs (concat bs))

但您可能通过将[a] 指定为包的参数而犯了一个错误,因此您可以修复类型并使用:

data ComposedType a = Set a | Bag a | Seq a deriving (Eq, Show)

getElements :: (Eq a, Ord a) => ComposedType [a] -> ComposedResult a
getElements (Set b) = Res1 (nub b)
getElements (Seq b) = Res1 (sort b)
getElements (Bag b) = Res2 (occrs b)

【讨论】:

  • 我认为你错过了一个大问题:ComposedType 根本没有使用SetBagSeq 类型别名:它只包含一个@987654352 @ 用 3 个构造函数之一装饰,这些构造函数的名称恰好与这些类型重叠。 Henrique N. Mendes 可能打算改为它实际上包含一个 Set、Bag 或 Seq。
猜你喜欢
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 1970-01-01
相关资源
最近更新 更多