我收到了这份作业(无法添加作业标签)。这只是一个训练问题,不是交接的一部分。 我创建了一个递归函数“eval”,用于评估整数上的常见操作(+、-、*、/) 到目前为止,该函数可以计算加法、乘法和减法。
type expr =
| Const of int
| Add of expr * expr
| Mul of expr * expr
| Sub of expr * expr
let rec eval (n: expr): int =
match n with
| Const n -> n
| Add (a, b) -> eval a + eval b
| Mul (a, b) -> eval a * eval b
| Sub (a, b) -> eval a - eval b
这个功能完美运行。接下来,我必须扩展 expr 类型,以允许除法,添加:
| Div of expr * expr
我还需要通过创建一个新类型来处理零除的情况:
('a, 'b) result
这是 eval 的新返回类型(这是在赋值描述中,所以我必须这样做)。 这是我的尝试:
type ('a, 'b) result =
| Ok of int
| Err of string
let rec eval (n: expr): ('a, 'b)result =
match n with
| Const n -> Ok(Const n)
| Add (a, b) -> Ok(eval a + eval b)
| Mul (a, b) -> OK(eval a * eval b)
| Sub (a, b) -> Ok(eval a - eval b)
| Div (_, Const 0) -> Err "zero division"
| Div (a, b) -> Ok(eval a / eval b)
但我收到一条错误消息,指出运算符 +、-、* 和/没有为类型 ('a, 'b) 结果定义,这是有道理的。所以我的问题是,有没有办法让新类型继承其他类型?我无法输入以下内容:
type ('a, 'b) result =
| int
| Err of string
为什么这不是一件事?如果我在新类型中使用 int ,是否必须指定一些与 int 相关联的关键字? f# 想要相同的输出类型,无论输入如何,有办法解决这个问题吗?如果我没有创建新类型,我可以告诉函数输出是整数还是字符串吗?
最佳答案
简短的回答是否定的。 正如您所说,F# 只允许一种返回类型。
在这种情况下,您的 result
类型有 2 组可能的值:Ok
值和 Error
值。
您的代码需要考虑这两种可能性,不能忽略其中一种。
请记住,eval a
不再返回int
,现在它返回一个结果
,该结果可能有也可能没有int
里面。
在eval a
和eval b
之后但在调用+
、-
、之前*
或 /
,您需要检查任一结果是否为 Error
。只有当两者都Ok
时,您才能应用该运算符。如果其中任何一个是错误
,您就必须返回错误,对吗?
您可以使用match
来检查(并提取int
),例如:
match eval a , eval b with
| Ok a', Ok b' -> Ok(a' + b')
| Error e , _
| _ , Error e -> Error e
请记住,您无需将上述说明复制 4 次。
您可以创建一个函数并将运算符作为参数传递
使用以下语法:(+)
、(-)
、(*)
、(/)
。
另一个提示:您只考虑除以 Const 0
的情况。
如果除以计算出的 0
(例如 5/(1 - 1)
),会发生什么?
在函数式编程中,还有另一种方法来处理这个问题。
您最终需要的是一个Bind
函数(或Apply>)。
这个网站是一个了解它的好资源:https://fsharpforfunandprofit.com/rop/
关于function - 有没有办法让函数根据输入返回整数或字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64578253/