简体   繁体   English

Map.lookup-类型声明错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM