首页 文章

Haskell List Comprehension调用多个参数时的非详尽模式

提问于
浏览
1

首先,我创建了一个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函数中有一个非详尽的模式 .

2 回答

  • 1

    让我们分析你的 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] ,这意味着它需要一个函数和一个列表并返回一个列表 . ( ab 只告诉编译器哪些类型必须相同 . )_ _182432_然后将函数应用于输入列表中的每个元素 .

    最后,您将了解部分功能应用和无点样式 . 使用这两个概念,使用 map 的版本可以略微简化:

    capMarks = map capMark
    

    不要太担心这个 . 我只是为了完整而添加它 .

  • 3

    您应该检查模式匹配在Haskell中的工作方式 .

    capMarks [x] 仅匹配具有一个元素的列表 . 您可能想要的是 capMarks myList = [ ... | ... <- f myList] 或以递归方式定义案例的休止符 .

    例如

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

    这个简化的“版本”在拥抱中起作用

    capMarks :: [Integer] -> [Integer]
    capMarks xs = [(*) 2 x | x <- xs]
    

相关问题