当模式匹配函数列表

问题描述

考虑以下代码

step :: [[a] -> [a]] -> [[a]] -> [[a]]
step (f:fs) xss
  | (fs == []) = yss
  | otherwise = step fs yss
  where yss = map f xss

它抛出以下错误

No instance for (Eq ([a] -> [a])) arising from a use of ‘==’
  (maybe you haven't applied a function to enough arguments?)

  |
3 |   | (fs == []) = res
  |      ^^^^^^^^

fs 应该是一个函数列表或者一个空列表,那么为什么编译器试图用它来生成一个函数

解决方法

只有在可以检查元素是否相等时(Eq 的实例),您才能检查列表是否相等。您可能认为这是无稽之谈,因为您正在与空列表进行比较,因此元素的值并不重要。但是在类型上,Haskell 将所有这些列表都看作只是列表,并且不知道它是否为空,因此它不能让比较发生。

幸运的是,有一个函数:null :: [a] -> Bool,用于检查列表是否为空:

step :: [[a] -> [a]] -> [[a]] -> [[a]]
step (f:fs) xss
  | null fs = yss
  | otherwise = step fs yss
  where yss = map f xss

(免责声明:null 实际上是为所有可折叠对象定义的,但出于我们的目的,您可以将其视为列表函数)

您还可以使用 pattern guard 进行模式匹配(因为模式匹配可以识别空列表):

step :: [[a] -> [a]] -> [[a]] -> [[a]]
step (f:fs) xss
  | [] <- fs = yss
  | otherwise = step fs yss
  where yss = map f xss

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...