Haskell Map.lookup-类型声明错误

Haskell Map.lookup-类型声明错误,haskell,Haskell,我正在使用代码: test2 :: Int -> Map Int Int -> Int test2 key cache | Map.member key cache = Map.lookup key cache | otherwise = 0 在这里,我想检查映射中Int的存在性,并查找该值(如果存在)。但我得到了一个错误: Couldn't match expected type `Int' with actual type `Maybe a0'

我正在使用代码:

test2 :: Int -> Map Int Int -> Int
test2 key cache 
      | Map.member key cache = Map.lookup key cache
      | otherwise = 0
在这里,我想检查映射中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

typechecker不够聪明,无法使用检查的语义事实来消除错误。为什么不呢

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)

typechecker不够聪明,无法使用检查的语义事实来消除错误。为什么不呢

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)
在您的情况下,查找的类型签名是

lookup :: Int -> Map Int Int -> Maybe Int
(!) :: Map Int Int -> Int -> Int
也就是说,它并不假设键在地图中,如果它不在地图中,它将什么也不会给你,如果它在地图中,它只会给你值

因为您使用的是守卫来声明密钥在地图中,所以您可以使用!相反就你而言,它的签名是

lookup :: Int -> Map Int Int -> Maybe Int
(!) :: Map Int Int -> Int -> Int
如果找不到密钥,它将抛出一个错误,但您已经在处理了。如果是你的话,你应该

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=findWithdefault0。

在您的例子中,查找的类型签名是

lookup :: Int -> Map Int Int -> Maybe Int
(!) :: Map Int Int -> Int -> Int
也就是说,它并不假设键在地图中,如果它不在地图中,它将什么也不会给你,如果它在地图中,它只会给你值

因为您使用的是守卫来声明密钥在地图中,所以您可以使用!相反就你而言,它的签名是

lookup :: Int -> Map Int Int -> Maybe Int
(!) :: Map Int Int -> Int -> Int
如果找不到密钥,它将抛出一个错误,但您已经在处理了。如果是你的话,你应该

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。

Map.lookup键缓存返回的可能是Int,而不是Int,因此编译错误

执行所需操作的最简单方法是使用Map.findWithDefault,如下所示:

如果要使用Map.lookup,可以执行以下操作:

test2 :: Int -> Map Int Int -> Int
test2 key cache = maybe 0 id . Map.lookup key $ cache
lookup key cache返回的可能是Int,而不是Int,因此编译错误

执行所需操作的最简单方法是使用Map.findWithDefault,如下所示:

如果要使用Map.lookup,可以执行以下操作:

test2 :: Int -> Map Int Int -> Int
test2 key cache = maybe 0 id . Map.lookup key $ cache

要解决新问题,只需使用

data Coord = Coord Int Int deriving (Show, Ord)
需要一个可排序的键类型,以便实际查找某些内容。对于像Coord这样同构于Int的简单结构,Haskell编译器可以自己计算出一个顺序


顺便说一句:我认为如果你的第一个问题解决了,你有了一个新问题,你应该提出一个新问题,因为你只能接受一个答案,这对帮助你解决第一部分问题的人来说是不公平的。

要解决你的新问题,只需使用

data Coord = Coord Int Int deriving (Show, Ord)
需要一个可排序的键类型,以便实际查找某些内容。对于像Coord这样同构于Int的简单结构,Haskell编译器可以自己计算出一个顺序


顺便说一句:我认为如果你的第一个问题解决了,你有了一个新问题,你应该提出一个新问题,因为你只能接受一个答案,这对在第一部分中帮助过你的人来说是不公平的。

你可以使用fromMaybe from Data来代替maybe 0 id。也许可以简单地将表达式写成:fromMaybe 0。Map.lookup key$cache。为了将数据类型用作映射中的键,它必须是Ord typeclass的实例,并且必须是可排序的。要为您的Coord数据类型自动派生Ord实例,只需将其添加到派生子句中:data Coord=Coord Int Int deriving Show,或不使用可能为0的id,您只需使用fromMaybe from data。可能只需将表达式编写为:fromMaybe 0。Map.lookup key$cache。为了将数据类型用作映射中的键,它必须是Ord typeclass的实例,并且必须是可排序的。要为您的Coord数据类型自动派生Ord实例,只需将其添加到派生子句中:data Coord=Coord Int Int deriving Show,Ord