Haskell 不能';t匹配类型‘;a’;与‘;区块’;在任何一种情况下
我正在尝试创建一个同时使用[Block]和[Ground]的函数。 为此,我声明该函数接收[a]和一个Int,该Int用作一个标志,用于保存每次调用该函数时我正在使用的其中一个列表的信息Haskell 不能';t匹配类型‘;a’;与‘;区块’;在任何一种情况下,haskell,Haskell,我正在尝试创建一个同时使用[Block]和[Ground]的函数。 为此,我声明该函数接收[a]和一个Int,该Int用作一个标志,用于保存每次调用该函数时我正在使用的其中一个列表的信息 printRow::[a]->Position->Int->[Picture] 打印行[]位置n=[] 打印行(h:t)(x,y)n | n==0=((打印块(右h)(x,y)):(打印行t(x+1,y)n)) |否则=((打印图块(左h)(x,y)):(打印行t(x+1,y)n)) printTile::块地
printRow::[a]->Position->Int->[Picture]
打印行[]位置n=[]
打印行(h:t)(x,y)n | n==0=((打印块(右h)(x,y)):(打印行t(x+1,y)n))
|否则=((打印图块(左h)(x,y)):(打印行t(x+1,y)n))
printTile::块地面->位置->图片
但是,我得到了以下错误:
Gloss.hs:47:51:错误:
•无法将类型“a”与“块”匹配
“a”是一个刚性类型变量,由
以下项的类型签名:
printRow::forall a。[a] ->Position->Int->[图片]
在光泽处。hs:44:11
预期类型:块或接地
实际类型:接地
•在“printTile”的第一个参数中,即“左h”
在“(:)”的第一个参数中,即
“(打印图块(左h)(x,y))”
在表达式中:
((打印图块(左h)(x,y)):(打印行t(x+1,y)n))
•相关绑定包括
t::[a](以光泽装订。hs:46:13)
h::a(以光泽装订。hs:46:11)
printRow::[a]->位置->整数->[图片]
(以光泽装订。hs:45:1)
正如Robin Zigmond所指出的,printRow
不能像您所说的那样一般,因为它传递给printTile
的值必须是块地类型,而不是任意类型的a
。因此,函数类型必须是
printRow :: [Either Block Ground] -> Position -> Int -> [Picture]
一旦进行了此更改,就不再需要Int
参数(无论如何,它应该是Bool
)
printRow [] _ = []
printRow (h:t) (x,y) = printTile h (x, y) : printRow t (x+1,y)
但是请注意,这几乎是zipWith
函数封装的模式:
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
您要做的是对一对值调用printTile
,一个是块地面
,另一个是更新的位置。您可以很容易地获得无限多个位置列表,用于[(x',y)|x'问题在于,您声明可以使用任何类型的列表调用printRow
。但是,您将其第一个值传递给一个函数,该函数希望它是块
。事实上,两个防护装置传递它的方式使得a
既需要是块
值,也需要是地面
,因此您无法通过简单地更改printRow
的类型签名来解决此问题。要么是实现错误,要么是printTile
的签名错误。@RobinZigmond我认为您的评论足以回答问题事实上,Int
参数(实际上可能是Bool
)是不必要的,因为printRow
应该具有type[orb Block Ground]->Position->[Picture]
;您只需将第一个参数的每个元素直接传递给printile
。事实上,printRow
本质上只是map printile
的一个变体。
printRow bgs (x,y) = zipWith printTile bgs [(x',y) | x' <- [x..]]
printRow :: Either [Board] [Ground] -> Position -> [Picture]
printRow bgs (x,y) = zipWith printTile (map which bgs) [(x',y) | x' <- [x..]]
where which = case bgs of
Right _ = Right
Left _ = Left