我正在编写一段返回函数的代码 像素列表,这是我定义的特殊数据类型,其类型如下:
data Pixel = Pixel {
color :: Float,
elevation :: Float,
distance: Float,
visited :: Bool
} deriving (Show)
我具有此功能,该功能将遍历两个文件并将它们放到一个像素列表中。这些文件分别包含颜色和高程,因此我继续获取此代码输出:
insertPixels :: [String] -> [String] -> [Pixel]
insertPixels _ _ = []
insertPixels (x:xs) (y:ys) = [Pixel (read x) (read y) 99999999 False] ++ insertPixels xs ys
当我尝试将其编译或加载到解释器中时,会出现此错误:
lab1.hs:33:1: warning: [-Woverlapping-patterns]
Pattern match is redundant
In an equation for ‘insertPixels’:
insertPixels (x : xs) (y : ys) = ...
|
| insertPixels (x:xs) (y:ys) = [Pixel (read x) (read y) 99999999 False] ++ insertPixels xs ys
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我不太了解这是什么意思或我做错了什么。
答案 0 :(得分:5)
只需切换两行的顺序,就像这样:
insertPixels :: [String] -> [String] -> [Pixel]
insertPixels (x:xs) (y:ys) = [Pixel (read x) (read y) 99999999 False] ++ insertPixels xs ys
insertPixels _ _ = []
问题在于insertPixels _ _
匹配所有内容,并且由于模式是从上至下进行评估的,因此在第一个匹配项时停止,因此所有可能的输入都将导致空列表-显然不是您想要的。经更正后,递归大小写将在两个输入列表均为非空时生效,并且一旦其中一个为空,它将归结为“包罗万象”的情况并导致空列表。
请注意,使用(++)
运算符将单个元素添加到列表的开头并不是特别习惯。您可以改用(:)
(“ cons”)运算符:
insertPixels :: [String] -> [String] -> [Pixel]
insertPixels (x:xs) (y:ys) = (Pixel (read x) (read y) 99999999 False) : insertPixels xs ys
insertPixels _ _ = []
答案 1 :(得分:1)
下划线_
是通配符,这意味着它与任何内容匹配:空列表,非空列表等。
因此,这意味着第一行将“触发”,无论您传递给insertPixels
的值是什么。没有输入模式的第二行将“触发”,因此发出警告。
我们可以在空列表上使用模式匹配,例如:
insertPixels :: [String] -> [String] -> [Pixel]
insertPixels [] _ = []
insertPixels _ [] = []
insertPixels (x:xs) (y:ys) = [Pixel (read x) (read y) 99999999 False] ++ insertPixels xs ys
但是,您在这里描述的是一种众所周知的模式。 zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
。因此,我们可以将insertPixel
定义为:
import Data.Function(on)
insertPixels :: [String] -> [String] -> [Pixel]
insertPixels = zipWith (\x y -> on Pixel read x y 99999999 False)
但是,我建议将read
从insertPixels
函数中删除,从而使用两个Float
列表。如果您想使用read
,则可以在呼叫者级别进行操作。