首先,我创建了一个Type 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函数中有一个非详尽的模式。
答案 0 :(得分: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
不要过分担心这个问题。我只是为了完整而在这里添加它。
答案 1 :(得分:1)
您应该检查模式匹配在Haskell中的工作方式。
capMarks [x]
只会将列表与一个元素匹配。你可能想要的是类似capMarks myList = [ ... | ... <- f myList]
的东西,或者以递归的方式定义案例的休止符。
例如
capMarks [] = []
capMarks x:xs = capMark x : capMarks xs
这个简化的&#34;版本&#34;在拥抱工作
capMarks :: [Integer] -> [Integer]
capMarks xs = [(*) 2 x | x <- xs]