Data.Map 函数作为 Haskell 中的值
Data.Map with functions as values in Haskell
我是一个 Haskell 新手,试图了解如何使用 Data.Map
结构、惰性求值和 Maybe
类型。
在Python中我可以定义一个字典结构,其值为函数。给定一个键我就可以使用相应的函数:
d = {"+": lambda x,y: x+y}
def f(key, v1, v2):
if key in d:
return d[key](v1, v2)
else:
return 0
我曾尝试在 Haskell 中做类似的事情,但它无法编译。
d = Map.fromList [('+', (+))]
f :: Char -> Integer -> Integer -> Integer
f key v1 v2 =
if k == Nothing
then 0
else f v1 v2
where
k = Map.lookup key d
(Just f) = k
这不会编译并且 returns 像
这样的错误
No instance for (Eq (Integer -> Integer -> Integer))
我相信这是因为 Map.lookup '+' d
只是 returns Maybe (Integer -> Integer -> Integer)
的一个实例,而不是 (Just (+))
或 Nothing
。我认为这与惰性评估有关。
有没有类似Haskell的方法来做这种事情?我是否错误地使用了 Maybe 类型?我可以强制对查找进行评估吗?
这是因为我试图在 Haskell 中实现反向抛光计算器。我用字典来组织我可能使用的功能。我找到了一个很好的解决方案 (https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#Haskell),但现在我只想了解如何正确访问 Haskell Data.Map
中的值。
确实,函数 (== Nothing)
作为类型 (Eq a) => Maybe a -> Bool
,在你的例子中,函数不是 Eq
类型类的成员,这不会编译。
但是您可以使用 Data.Maybe
中的 isNothing
函数,或者您可以像这样自己定义它:
isNothing :: Maybe a -> Bool
isNothing Nothing = True
isNothing (Just _) = False
因为您在构造函数上进行模式匹配,因此不使用 (==)
,所以您不需要 a
成为 Eq
.
的实例
问题是这个表达式:k == Nothing
需要k
支持相等性测试。 k
的类型是 Maybe (Integer -> Integer -> Integer)
。如果 T
支持,Maybe T
支持相等性测试,但 Integer -> Integer -> Integer
不支持:您无法比较函数的相等性。所以整个表达式没有类型检查。
我不知道你所说的“Maybe (Integer -> Integer -> Integer)
的实例”是什么意思:类 有实例(类型),但是Maybe (Integer -> Integer -> Integer)
不是class,是普通类型。有问题的 class 是 Eq
(它提供了 ==
方法)。问题是函数类型没有 Eq
实例。这也与惰性求值无关。
解决方案是只使用模式匹配:
f key v1 v2 =
case Map.lookup key d of
Nothing -> 0
Just f -> f v1 v2
-- but consider naming 'f' something else;
-- the surrounding function is already called 'f'
或者,您可以使用 Maybe
辅助函数之一:
f key v1 v2 =
maybe 0 (\f -> f v1 v2) (Map.lookup key d)
甚至:
f key v1 v2 =
fromMaybe (\_ _ -> 0) (Map.lookup key d) v1 v2
这是因为您在比较表达式中使用了类型为 Maybe (Integer -> Integer -> Integer)
的 k
。 Haskell 不知道如何比较两个函数。
一个解决方案是'unpack'查找的return。
import qualified Data.Map as Map
d = Map.fromList [('+', (+))]
f :: Char -> Integer -> Integer -> Integer
f key v1 v2 =
case Map.lookup key d of
Nothing -> 0
Just f -> f v1 v2
.
λ> f '-' 1 2
0
λ> f '+' 1 2
3
λ>
我是一个 Haskell 新手,试图了解如何使用 Data.Map
结构、惰性求值和 Maybe
类型。
在Python中我可以定义一个字典结构,其值为函数。给定一个键我就可以使用相应的函数:
d = {"+": lambda x,y: x+y}
def f(key, v1, v2):
if key in d:
return d[key](v1, v2)
else:
return 0
我曾尝试在 Haskell 中做类似的事情,但它无法编译。
d = Map.fromList [('+', (+))]
f :: Char -> Integer -> Integer -> Integer
f key v1 v2 =
if k == Nothing
then 0
else f v1 v2
where
k = Map.lookup key d
(Just f) = k
这不会编译并且 returns 像
这样的错误No instance for (Eq (Integer -> Integer -> Integer))
我相信这是因为 Map.lookup '+' d
只是 returns Maybe (Integer -> Integer -> Integer)
的一个实例,而不是 (Just (+))
或 Nothing
。我认为这与惰性评估有关。
有没有类似Haskell的方法来做这种事情?我是否错误地使用了 Maybe 类型?我可以强制对查找进行评估吗?
这是因为我试图在 Haskell 中实现反向抛光计算器。我用字典来组织我可能使用的功能。我找到了一个很好的解决方案 (https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#Haskell),但现在我只想了解如何正确访问 Haskell Data.Map
中的值。
确实,函数 (== Nothing)
作为类型 (Eq a) => Maybe a -> Bool
,在你的例子中,函数不是 Eq
类型类的成员,这不会编译。
但是您可以使用 Data.Maybe
中的 isNothing
函数,或者您可以像这样自己定义它:
isNothing :: Maybe a -> Bool
isNothing Nothing = True
isNothing (Just _) = False
因为您在构造函数上进行模式匹配,因此不使用 (==)
,所以您不需要 a
成为 Eq
.
问题是这个表达式:k == Nothing
需要k
支持相等性测试。 k
的类型是 Maybe (Integer -> Integer -> Integer)
。如果 T
支持,Maybe T
支持相等性测试,但 Integer -> Integer -> Integer
不支持:您无法比较函数的相等性。所以整个表达式没有类型检查。
我不知道你所说的“Maybe (Integer -> Integer -> Integer)
的实例”是什么意思:类 有实例(类型),但是Maybe (Integer -> Integer -> Integer)
不是class,是普通类型。有问题的 class 是 Eq
(它提供了 ==
方法)。问题是函数类型没有 Eq
实例。这也与惰性求值无关。
解决方案是只使用模式匹配:
f key v1 v2 =
case Map.lookup key d of
Nothing -> 0
Just f -> f v1 v2
-- but consider naming 'f' something else;
-- the surrounding function is already called 'f'
或者,您可以使用 Maybe
辅助函数之一:
f key v1 v2 =
maybe 0 (\f -> f v1 v2) (Map.lookup key d)
甚至:
f key v1 v2 =
fromMaybe (\_ _ -> 0) (Map.lookup key d) v1 v2
这是因为您在比较表达式中使用了类型为 Maybe (Integer -> Integer -> Integer)
的 k
。 Haskell 不知道如何比较两个函数。
一个解决方案是'unpack'查找的return。
import qualified Data.Map as Map
d = Map.fromList [('+', (+))]
f :: Char -> Integer -> Integer -> Integer
f key v1 v2 =
case Map.lookup key d of
Nothing -> 0
Just f -> f v1 v2
.
λ> f '-' 1 2
0
λ> f '+' 1 2
3
λ>