我正在处理代码:
test2 :: Int -> Map Int Int -> Int
test2 key cache
| Map.member key cache = Map.lookup key cache
| otherwise = 0
这里我想检查Map中Int的存在并查找值(如果存在)。但我得到错误:
Couldn't match expected type `Int' with actual type `Maybe a0'
In the return type of a call of `Map.lookup'
In the expression: Map.lookup key cache
In an equation for `test2':
test2 key cache
| member key cache = Map.lookup key cache
| otherwise = 0
为什么呢?我已经检查了地图中密钥的存在。我该如何解决?
更新
渴望得到答案,但我的真实代码有点复杂:
data Coord = Coord Int Int deriving (Show)
calculation :: Coord -> Map Coord Integer -> Integer
calculation coord cache
| corner coord = 0
| side coord = 1
| Map.member coord cache = Map.lookup key cache
| otherwise = (calculation (move_right coord) cache) + (calculation (move_down coord) cache)
where (Coord x y) = coord
我更新了这样的代码:
calculation :: Coord -> Map Coord Integer -> Integer
calculation coord cache
| corner coord = 0
| side coord = 1
| Map.member coord cache = Map.findWithDefault (calculation (move_right coord) cache) + (calculation (move_down coord) cache) coord cache
where (Coord x y) = coord
但是得到下一个错误:
problem_15.hs:21:14:
No instance for (Ord Coord)
arising from a use of `member'
Possible fix: add an instance declaration for (Ord Coord)
In the expression: member coord cache
In a stmt of a pattern guard for
an equation for `calculation':
member coord cache
In an equation for `calculation':
calculation coord cache
| corner coord = 0
| side coord = 1
| member coord cache
= findWithDefault (calculation (move_right coord) cache)
+ (calculation (move_down coord) cache) coord cache
where
(Coord x y) = coord
problem_15.hs:21:39:
Couldn't match expected type `Integer'
with actual type `k0 -> Map k0 a0 -> a0'
In the return type of a call of `findWithDefault'
In the first argument of `(+)', namely
`findWithDefault (calculation (move_right coord) cache)'
In the expression:
findWithDefault (calculation (move_right coord) cache)
+ (calculation (move_down coord) cache) coord cache
答案 0 :(得分:7)
Map.lookup key cache
返回一个Maybe Int,而不是Int,因此编译错误。
执行所需操作的最简单方法是使用Map.findWithDefault
,如下所示:
test2 :: Int -> Map Int Int -> Int
test2 key cache = Map.findWithDefault 0 key cache
如果您想使用Map.lookup
,可以执行以下操作:
test2 :: Int -> Map Int Int -> Int
test2 key cache = maybe 0 id . Map.lookup key $ cache
答案 1 :(得分:4)
test2 key cache
| Map.member key cache = fromJust $ Map.lookup key cache
| otherwise = 0
需要fromJust
或更具惯用性
test2 key cache
| Map.member key cache = cache ! key
| otherwise = 0
甚至更好
test2 key cache = case Map.lookup key cache of
Just x -> x
Nothing -> 1
或者,理想情况下
test2 key cache = maybe 0 id (Map.lookup key cache)
答案 2 :(得分:2)
lookup
的类型签名,在您的情况下,
lookup :: Int -> Map Int Int -> Maybe Int
也就是说,它不会假设密钥在地图中(如果密钥不在,它会给你Nothing
,Just value
如果它在那里有值value
)。
由于您正在使用警卫断言地图中的 键,因此您可以使用(!)
代替。在您的情况下,它的签名是
(!) :: Map Int Int -> Int -> Int
如果无法找到密钥,它会抛出error
,但您已经在处理它了。在你的情况下,你有
test2 :: Int -> Map Int Int -> Int
test2 key cache
| Map.member key cache = cache Map.! key
| otherwise = 0
附录:请注意,Data.Map
已经附带了一个与test2
完全相同的功能,即
findWithDefault :: Ord k => a -> k -> Map k a -> a
您会看到test2 = findWithDefault 0
。
答案 3 :(得分:1)
要修复新问题,请使用
data Coord = Coord Int Int deriving (Show, Ord)
member需要一个“可排序”键类型才能真正查找内容。对于像Coord
这样简单的结构(与(Int, Int)
是同构的),Haskell编译器可以自己计算出一个顺序。