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