我有这个问题: 我希望有一个表示数学表达式的字符串列表,以及一个替换变量的参数映射。 所以,如果我的列表像[“x”,“+”,“y”,“ - ”,“5”],参数是[(“x”,“5”),(“y”,“4”) ] 该函数应返回[“5”,“+”,“4”,“ - ”,“5”]
我有这个功能可以从地图中找到钥匙(来自“了解你的哈克尔书”)
findKey :: (Eq k) => k -> [(k,v)] -> Maybe v
findKey key [] = Nothing
findKey key ((k,v): xs) =
if key == k
then Just v
else findKey key xs
然后我的函数用值
替换变量takeValuesFromMap (x:str) m result
|x == [] = result
|findKey x m == Nothing = takeValuesFromMap str m (result++[x])
|otherwise = takeValuesFromMap str m result++[fromJust (findKey x m)]
如果地图中没有匹配,我们会传递常规字符串。否则,我们将匹配的密钥旁边的值传递给结果。
但最后我打电话
takeValuesFromMap ["x","+","y","-","5"] (Map.fromList [("x","5"),("y","4")]) []
它说
Solver.hs:63:48:
Couldn't match expected type `[([Char], [Char])]'
with actual type `Map.Map [Char] [Char]'
In the return type of a call of `Map.fromList'
In the second argument of `takeValuesFromMap', namely
`(Map.fromList [("x", "5"), ("y", "4")])'
In the expression:
takeValuesFromMap
["x", "+", "y", "-", ....]
(Map.fromList [("x", "5"), ("y", "4")])
[]
任何想法如何解决这个问题?
答案 0 :(得分:1)
我将在这里采取不同的轨道,并建议您不解决此问题。原因是列表["x","+","y","-","5"]
是代数表达式x + y - 5
的非常差的表示。我不确切地知道你要做什么,但更好的方法是使用代数数据类型将表达式表示为抽象语法树。
例如,我们可以使用以下类型来表示表达式:
data Expr a = Variable String
| Literal a
| Plus Expr Expr
| Minus Expr Expr
鉴于此类型,您的示例如下:
example :: Expr Integer
example = Minus (Plus (Var "x") (Var "y")) (Literal 5)
编写一个评估此类表达式的函数很容易,给定从变量名到值的Map
:
-- | Evaluate an expression, reading variable's values from the given environment
-- (the Map argument). Returns Nothing if any of the variables is undefined.
eval :: Num a => Expr a -> Map String a -> Maybe a
eval (Variable v) env = Map.lookup v env
eval (Literal x) _ = Just x
eval (Plus x y) env =
-- If this is confusing, read up on the Maybe monad in Learn You a Haskell
do x' <- eval x env
y' <- eval y env
return (x + y)
eval (Minus x y) env =
do x' <- eval x env
y' <- eval y env
return (x - y)
更复杂但值得学习的是编写一个解析器,它接受一个字符串并将其转换为Expr
。如果您正在阅读了解您的Haskell ,您可能希望首先更加熟悉monad和applicatives。但是当你准备好采取这一步骤时,网上有很多页面都有计算器解析器的例子:
虽然您可能想首先阅读 Real World Haskell 的这一部分:
答案 1 :(得分:0)
在findKey
中,您需要一个关联列表,但实际上您正在使用地图。因此,修复它的一种方法是删除Map.fromList
。
另一点:永远不要用等式检查替换模式匹配!所以请写下:
| [] <- x = ...
| Nothing <- findKey x m = ...
答案 2 :(得分:0)
检查Map.fromList
的类型。假设您从Map
开始Data.Map
,我是否正确?如果是这样的话:
:t Data.Map.fromList
Data.Map.fromList :: Ord k => [(k, a)] -> Map k a
因此,此函数返回Map,但您的findKey
实际需要一个元组列表[([Char],[Char])]
。你现在有两个选择:
Data.Map
而非findKey
的功能查找密钥。