ocaml - ocaml 类型的初学者
问题描述
这可能是一个简单的问题,但我不确定为什么会出现此错误:
我在文件中定义了一个类型
type tree = TreeNode of string * tree list;;
我在另一个[编辑添加的getFt和getSt函数]中有这个函数定义
let getFt input = match input with
| (x, y) -> x;;
let getSt input = match input with
| (x, y) -> y;;
let rec traverse input =
match (getFt(input)) with
| "S" -> nodeS (getSt(input))
| "T" -> nodeT (getSt(input))
and traverseList input =
match (getFt(List.hd(input))) with
| "S" -> nodeS (List.tl(input))
| "T" -> nodeT (List.tl(input))
and nodeS input =
match (getFt(List.hd(input))) with
| "TRUE" -> (TreeNode("TRUE", []))
| "FALSE" -> (TreeNode("FALSE", []))
| "(" -> (traverseList (List.tl(input)))
| x -> (TreeNode(x, []))
and nodeT input =
match (getFt(List.hd(input))) with
| "not" -> (TreeNode("not", [(nodeS (List.tl(input)))]))
| "and" -> (TreeNode("and", [(traverseList (List.tl(input)) )]))
| "or" -> (TreeNode("or", []));;
let buildAbstractSyntaxTree (input : tree) : tree = traverse input;;
并且每当我编译时都会收到此错误:[编辑我输入了错误的错误]
Error: This expression has type Proj2_types.tree
but an expression was expected of type string * (string * 'a) list
解决方案
这个答案不是为了取代 Jeffrey 的答案,而是为了给你一些关于你进一步 OCaml 代码的提示。
TL; DR:字符串是“坏的”
如果我正确阅读了您的代码,则您的树是一对包装的树Treenode of string * tree list
(它看起来并不像一棵树,而更像是一条路径,因为您没有左分支和右分支,因此您有一个节点后跟什么都没有或另一个节点等。实际上你刚刚定义了一个列表;-))
你开始匹配它从traverse
.
traverse
看看这对的第一部分是字符串"S"
还是字符串"T"
,所以让我们重写它:
let rec traverse = function
| Treenode ("S", t) -> nodeS t
| Treenode ("T", t) -> nodeT t
做什么nodeS
?它匹配列表头部的第一部分,并检查它是否为、"TRUE"
或其他任何内容。如果它是前两个,它只是创建一个 new ,它是遍历剩余列表的括号,如果它是其他任何东西,它只是用它创建一个 new 。因此,您有 3 个案例做完全相同的事情,但您为每个案例做了一个案例。让我们重写它:"FALSE"
"("
TreeNode
TreeNode
and nodeS = function
| [] -> failwith "TODO"
| ("(", _) :: tl -> traverseList tl
| (x, _) :: _ -> TreeNode (x, [])
至于nodeT
,我们要么期望找到"and"
,"or"
要么"not"
给出:
and nodeT = function
| [] -> failwith "TODO"
| ("not", _) :: tl -> TreeNode("not", [nodeS tl])
| ("and", _) :: tl -> TreeNode("and", [traverseList tl])
| ("or", _) :: tl -> TreeNode("or", [])
最后,traverseList:
and traverseList = function
| [] -> failwith "TODO"
| ("S", _) :: tl -> nodeS tl
| ("T", _) :: tl -> nodeT tl
问题出现。首先,您不处理空列表(我的 `failwith "TODO"),但最重要的是,您操作字符串,如果您将“A”作为第一个字符串会发生什么?从你如何构建你的树可能是不可能的,但它没有按类型显示。这就是 sum 类型可以帮助您的地方。尝试像这样重新定义你的树:
type node = S | T | True | False | Par | Not | And | Or
type tree = TreeNode of node * tree list
看看它会把你引向何方。OCaml 强烈强调由类型引导的风格。字符串对文本有用,但对类型有用(想象一下,如果你开始在 AST 中添加自定义函数,你会匹配“myfun of int -> int -> string”吗?听起来很乏味,你不同意吗?)
我希望你能阅读我的代码(和 Jeffrey 的代码)并发现 OCaml 中的模式匹配是多么强大,这意味着你不必使用你的getFt
和getSt
函数。如果您有任何问题,请随时发表评论,这里的人很乐意提供帮助;-)
推荐阅读
- c - 指针中的分段错误
- android - 安卓。将文件保存到设备上的共享目录中
- sas - 在 SAS 中生成新变量会导致错误 180-322
- python-3.x - 无法启动 docker `OSError: [Errno 8] Exec format error: '/usr/local/bin/docker-credential-ecr-login'`
- javascript - 将汉堡菜单移动到右侧 react-burger-menu
- kubernetes - 找不到服务“istio-sidecar-injector”
- python - 从数据框列中的字符串中删除 numpy 数组中存在的特定单词?[Python]
- c# - AspNet 核心无法读取 FromQuery 参数
- javascript - 在反应钩子状态不保留其先前的状态
- reactjs - 如何通过在反应中使用onclick按钮将不同的js文件输出调用到另一个js文件