1

首先,我创建了一个类型 StudentMark,它是一个元组,首先是一个字符串,其次是一个 Int。

type StudentMark = (String, Int)

这是我的 capMarks 函数:

capMarks :: [StudentMark] -> [StudentMark]
capMarks [cMarks] = [(st, mk) | (st, mk) <- [capMark cMarks]]

这是我的 capMark 函数:

capMark :: StudentMark -> StudentMark
capMark (st, mk)
    |   mk > 39   =   (st, 40)
    |   mk < 40   =   (st, mk)

它应该返回:

[("Jo", 37), ("Sam", 40)]

从:

capMarks [("Jo", 37), ("Sam", 76)]

但是只有当我在函数中输入 1 个参数时才会返回正确和预期的响应,例如:

capMarks [("Jake", 50)]

或者

capMarks [("Jake"), 30]

但是按照预期使用两个(或更多)只会告诉我 capMarks 函数中有一个非穷举模式。

4

2 回答 2

4

让我们分析一下您的capMarks功能:

capMarks :: [StudentMark] -> [StudentMark]
capMarks [cMarks] = [(st, mk) | (st, mk) <- [capMark cMarks]]

首先capMarks [cMarks] = ...是模式匹配。这匹配包含单个元素的列表。我假设您想对整个列表执行某些操作,因此将其更改为capMarks cMarks = ...

接下来... [(st, mk) | (st, mk) <- [capMark cMarks]]将把capMark函数应用于原始模式匹配方案中的唯一元素,然后将结果作为列表的唯一元素。看来您想应用于capMark列表的每个元素。因此,如果我们按照之前的建议,您需要执行类似... [capMark mark | mark <- cMarks]. 这与前面所说的完全一样:适用capMark于列表的每个元素cMarks

最终版本:

capMarks :: [StudentMark] -> [StudentMark]
capMarks cMarks = [capMark mark | mark <- cMarks]

或者,您也可以使用模式匹配和显式递归:

capMarks [] = []  
capMarks (x:xs) = capMark x : capMarks xs

第一行说capMarks应用于空列表的是一个空列表。第二行表示capMarks应用于具有至少一个元素的列表将应用于capMark第一个元素,然后递归地应用于capMarks列表的其余部分。

这是 Haskell 中的一种常见模式,以至于有一个函数map可以概括它。使用map非常简单:

capMarks cMarks = map capMark cMarks

map有类型(a -> b) -> [a] -> [b],这意味着它需要一个函数和一个列表并返回一个列表。(a并且b只是告诉编译器哪些类型必须相同。)map然后将该函数应用于输入列表中的每个元素。

最终您将了解偏函数应用和无点样式。有了这两个概念,使用的版本map可以稍微简化一下:

capMarks = map capMark

不要太担心这个。为了完整起见,我只是在这里添加它。

于 2016-01-22T18:26:55.677 回答
1

您应该检查模式匹配在 Haskell 中是如何工作的。

capMarks [x]只会匹配一个包含一个元素的列表。您可能想要的是类似capMarks myList = [ ... | ... <- f myList]或以递归方式定义其余案例。

例如

capMarks [] = []
capMarks x:xs = capMark x : capMarks xs

这个简化的“版本”适用于拥抱

capMarks :: [Integer] -> [Integer]
capMarks xs = [(*) 2 x | x <- xs]
于 2016-01-22T18:14:41.403 回答