[英]Map.lookup - type declaration error
I am working with code: 我正在使用代码:
test2 :: Int -> Map Int Int -> Int
test2 key cache
| Map.member key cache = Map.lookup key cache
| otherwise = 0
Here I want to check the existance of Int in the Map and lookup the value if it exists. 在这里,我想检查Map中Int的存在并查找值(如果存在)。 But I get error:
但是我得到了错误:
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
Why? 为什么? I have checked existance of key in the Map.
我检查了地图中钥匙的存在。 How can I fix it?
我该如何解决?
Updated 更新
Thans for your answers, but my real code is a little bit complex: 谢谢您的回答,但是我的实际代码有些复杂:
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
I have updated the code like this: 我已经更新了这样的代码:
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
But get the next error: 但是得到下一个错误:
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
Map.lookup key cache
returns a Maybe Int, not an Int, thus the compile error. Map.lookup key cache
将返回Maybe Int,而不是Int,从而导致编译错误。
The easiest way to do what you want is to use Map.findWithDefault
like so: 执行所需操作的最简单方法是使用
Map.findWithDefault
如下所示:
test2 :: Int -> Map Int Int -> Int
test2 key cache = Map.findWithDefault 0 key cache
If you want to use Map.lookup
, you can do the following: 如果要使用
Map.lookup
,可以执行以下操作:
test2 :: Int -> Map Int Int -> Int
test2 key cache = maybe 0 id . Map.lookup key $ cache
the typechecker isn't smart enough to use the semantic fact of your check to eliminate the maybe. typechecker不够聪明,无法使用检查的语义事实来消除可能的情况。 Why not
为什么不
test2 key cache
| Map.member key cache = fromJust $ Map.lookup key cache
| otherwise = 0
which requires fromJust
or the more idiomatically 这就需要
fromJust
test2 key cache
| Map.member key cache = cache ! key
| otherwise = 0
or even better 甚至更好
test2 key cache = case Map.lookup key cache of
Just x -> x
Nothing -> 1
or, ideally 或者,理想情况下
test2 key cache = maybe 0 id (Map.lookup key cache)
The type signature of lookup
is, in your case, 在您的情况下,
lookup
的类型签名是
lookup :: Int -> Map Int Int -> Maybe Int
That is, it does not assume that the key is in the map (it'll give you Nothing
if it isn't, Just value
if it's in there with value value
). 也就是说,它不假定键在地图中(如果不存在,它将为您提供
Nothing
如果其中包含Just value
,它将为您提供Just value
value
)。
Since you're using guards to assert that key is in the map, you could use (!)
instead. 由于您使用的警卫断言,关键是在地图上,你可以使用
(!)
来代替。 Its signature is, in your case, 您的签名是
(!) :: Map Int Int -> Int -> Int
It'll throw an error
if the key cannot be found, but you're already handling that. 如果找不到密钥,它将引发
error
,但是您已经在处理该错误。 In your case you'd have 就你而言
test2 :: Int -> Map Int Int -> Int
test2 key cache
| Map.member key cache = cache Map.! key
| otherwise = 0
Addendum: Do note, though, that Data.Map
already comes with a function that does just what your test2
does, namely 附录:不过,请注意,
Data.Map
已经带有一个功能,该功能可以完成您的test2
要做的工作,即
findWithDefault :: Ord k => a -> k -> Map k a -> a
You'll see that test2 = findWithDefault 0
. 您会看到
test2 = findWithDefault 0
。
To fix your new problem, just use 要解决新问题,只需使用
data Coord = Coord Int Int deriving (Show, Ord)
member needs a "sortable" key type in order to actually look something up. 成员需要一个“可排序”键类型才能实际查找内容。 For easy structures like
Coord
(which is isomorphic to (Int, Int)
) the Haskell compiler can figure out an order by itself. 对于像
Coord
这样的简单结构(与(Int, Int)
同构),Haskell编译器可以自己找出一个顺序。
BTW: I think if your first problem is solved and you have a new one, you should open a new question, as you can accept only one answer, which isn't very fair to the people who helped you with the first part. 顺便说一句:我认为,如果您的第一个问题解决了,并且您有一个新问题,您应该打开一个新问题,因为您只能接受一个答案,这对于在第一部分中为您提供帮助的人们而言并不公平。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.