我首先要说的是我对Haskell很新,所以我还没有学过像Monads这样的东西。
在Haskell中,我正在尝试创建一种树,其中数字作为叶子,并且作为分支起作用,因此整个树可以像计算器一样。
到目前为止,这是我的代码。目前我没有将功能作为输入,而只是使用字符。
data Tree3 = Leaf3 Int | Node3 Char Tree3 Tree3 deriving (Show)
-- I would like to replace this ^ Char somehow with a function.
evaluate :: Tree3 -> Int
evaluate (Leaf3 x) = x
evaluate (Node3 c m n) | c == '+' = evaluate m + evaluate n
| c == '-' = evaluate m - evaluate n
| c == '/' = evaluate m `div` evaluate n
| c == '*' = evaluate m * evaluate n
所以我的问题是我可以在数据结构中输入一个函数(该类型是什么?)
对于可能令人困惑的问题感到抱歉,但感谢您的任何建议!
答案 0 :(得分:5)
我建议你把树写成:
data Tree = Leaf Int | Node (Int -> Int -> Int) Tree Tree
请注意,您无法派生Eq
或Show
,因为Int -> Int
没有实现其中任何一个类型类(并且它们都是不可能 不切实际这样做。)
然后您可以将evaluate
功能编写为
evaluate :: Tree -> Int
evaluate (Leaf x) = x
evaluate (Node f l r) = f (evaluate l) (evaluate r)
这简单得多!
您可以创建一个树来表示像(1 + 2) * (3 * 4)
这样的表达式
expr :: Tree
expr = Node (*) (Node (+) (Leaf 1) (Leaf 2)) (Node (*) (Leaf 3) (Leaf 4))
另一种方法可以让你更容易打印你的树,那就是使用几乎相同的定义:
data Tree = Leaf Int | Node String Tree Tree
-- ^ String instead of Char
然后,如果您导入了Data.Map
,则可以创建要查找的函数映射,但这会使您的evaluate
函数更复杂,因为您介绍了函数获胜的可能性&#39 ;在你的地图上。幸运的是,Haskell有一些非常方便的工具可以优雅地处理它!
import qualified Data.Map as Map
type Tree = Leaf Int | Node String Tree Tree deriving (Eq, Show)
type FuncMap = Map.Map String (Int -> Int -> Int)
evaluate :: FuncMap -> Tree -> Maybe Tree
evaluate funcs (Leaf x) = return x
evaluate funcs (Node funcName left right) = do
-- Use qualified import since there's a Prelude.lookup
f <- Map.lookup funcName funcs
l <- evaluate funcs left
r <- evaluate funcs right
return $ f l r
如果尝试类似
,这将自动生成Nothing
evaluate (Map.fromList [("+", (+))]) (Node "blah" (Leaf 1) (Leaf 2))
因为"blah"
中的函数FuncMap
不存在。请注意,由于Maybe
的monad实例,我们无法进行任何类型的显式错误处理!如果函数映射的任何查找返回Nothing
,则整个计算返回Nothing
,而我们不必考虑它。