Sml 如何返回某个列表而不是普通列表?

Sml 如何返回某个列表而不是普通列表?,sml,smlnj,Sml,Smlnj,我正在尝试实现一个程序,该程序接受一个字符串和一个列表,如果没有找到任何匹配项,则返回NONE,如果找到匹配项,则返回不带元素的列表 fun all_except_option ("string",["he","she","string"]) = SOME["he","she"] all_except_option ("string",["he&

我正在尝试实现一个程序,该程序接受一个字符串和一个列表,如果没有找到任何匹配项,则返回
NONE
,如果找到匹配项,则返回不带元素的列表

fun all_except_option ("string",["he","she","string"]) = SOME["he","she"]
all_except_option ("string",["he","she","string"]) = SOME ["he","she"]
我已经设法使它工作,但没有选项类型,我不知道如何使它返回
一些列表
,而不是一个正常的列表

fun all_except_option(str,lst)=
    case lst of
         [] => []
      | x::lst' => if same_string(x,str) = false
                   then let fun append (word, list) = word::list
                        in append(x,[]) :: all_except_option(str,lst')
                        end
                   else all_except_option(str,lst')

多谢各位。我设法让它工作,但我仍然不理解“else case”以及我的程序是如何处理它的。这是工作代码。如果您能给我解释一下“除选项(str,list)外的所有其他情况”,我将非常高兴


多谢各位。我设法让它工作,但我仍然不理解“else case”以及我的程序是如何处理它的。这是工作代码。如果您能给我解释一下“除选项(str,list)外的所有其他情况”,我将非常高兴

实现一个程序,该程序接受一个字符串和一个列表,如果未找到任何匹配项,则返回
NONE
,如果找到匹配项,则返回不带元素的列表

fun all_except_option ("string",["he","she","string"]) = SOME["he","she"]
all_except_option ("string",["he","she","string"]) = SOME ["he","she"]
SOME[]
NONE
有何不同?与中一样,如果此函数仅返回一个列表,则可以说删除出现的
“string”
不会导致其他字符串:要么列表已为空,要么它只包含出现的
“string”
。我不知道为什么
某些[]
在一种情况下比另一种情况下更有保障

因此,更好的函数是只返回普通列表的函数:

fun except (x, ys) = List.filter (fn y => x <> y)
此函数返回0或1。但它也是一个简单的函数,因为它从不通过递归聚合结果。递归函数在返回复合数据类型时变得复杂,比如“当需要解包递归结果时,返回一个选项”

一个很好的例子是
eval
函数有时会失败:

datatype expr
  = Add of expr * expr
  | Sub of expr * expr
  | Mul of expr * expr
  | Div of expr * expr
  | Int of int

fun eval (Int n) = SOME n
  | eval (Add (e1, e2)) = evalHelper ( op+ ) (e1, e2)
  | eval (Sub (e1, e2)) = evalHelper ( op- ) (e1, e2)
  | eval (Mul (e1, e2)) = evalHelper ( op* ) (e1, e2)
  | eval (Div (e1, e2)) =
      case eval e1 of
           NONE => NONE
         | SOME x => case eval e2 of
                          NONE => NONE
                        | SOME 0 => NONE
                        | SOME y => SOME (x div y)

and evalHelper binop (e1, e2) =
      case eval e1 of
           NONE => NONE
         | SOME x => case eval e2 of
                          NONE => NONE
                        | SOME y => SOME (binop (x, y))
这里的返回类型是int选项,这意味着您最常返回一个int,但如果您被零除,则结果为“无值”,因此,我们不会引发异常,而是返回
NONE
,这要求我们在有结果时返回
SOME n
,以便该类型适合这两种情况

快速演示:

- eval (Div (Int 5, Int 2));
> val it = SOME 2 : int option
- eval (Div (Int 5, Int 0));
> val it = NONE : int option
- eval (Div (Int 2, Sub (Int 3, Int 3)));
> val it = NONE : int option
- eval (Div (Int 0, Int 1));
> val it = SOME 0 : int option
这里的一些0实际上意味着“结果是0”,这与“不能被零除”不同

实现一个程序,该程序接受一个字符串和一个列表,如果未找到任何匹配项,则返回
NONE
,如果找到匹配项,则返回不带元素的列表

fun all_except_option ("string",["he","she","string"]) = SOME["he","she"]
all_except_option ("string",["he","she","string"]) = SOME ["he","she"]
SOME[]
NONE
有何不同?与中一样,如果此函数仅返回一个列表,则可以说删除出现的
“string”
不会导致其他字符串:要么列表已为空,要么它只包含出现的
“string”
。我不知道为什么
某些[]
在一种情况下比另一种情况下更有保障

因此,更好的函数是只返回普通列表的函数:

fun except (x, ys) = List.filter (fn y => x <> y)
此函数返回0或1。但它也是一个简单的函数,因为它从不通过递归聚合结果。递归函数在返回复合数据类型时变得复杂,比如“当需要解包递归结果时,返回一个选项”

一个很好的例子是
eval
函数有时会失败:

datatype expr
  = Add of expr * expr
  | Sub of expr * expr
  | Mul of expr * expr
  | Div of expr * expr
  | Int of int

fun eval (Int n) = SOME n
  | eval (Add (e1, e2)) = evalHelper ( op+ ) (e1, e2)
  | eval (Sub (e1, e2)) = evalHelper ( op- ) (e1, e2)
  | eval (Mul (e1, e2)) = evalHelper ( op* ) (e1, e2)
  | eval (Div (e1, e2)) =
      case eval e1 of
           NONE => NONE
         | SOME x => case eval e2 of
                          NONE => NONE
                        | SOME 0 => NONE
                        | SOME y => SOME (x div y)

and evalHelper binop (e1, e2) =
      case eval e1 of
           NONE => NONE
         | SOME x => case eval e2 of
                          NONE => NONE
                        | SOME y => SOME (binop (x, y))
这里的返回类型是int选项,这意味着您最常返回一个int,但如果您被零除,则结果为“无值”,因此,我们不会引发异常,而是返回
NONE
,这要求我们在有结果时返回
SOME n
,以便该类型适合这两种情况

快速演示:

- eval (Div (Int 5, Int 2));
> val it = SOME 2 : int option
- eval (Div (Int 5, Int 0));
> val it = NONE : int option
- eval (Div (Int 2, Sub (Int 3, Int 3)));
> val it = NONE : int option
- eval (Div (Int 0, Int 1));
> val it = SOME 0 : int option

这里有些0实际上意味着“结果是0”,这与“不能被零除”不同。

这是不正确的。为什么要删除递归并将其替换为
SOME
?您的
NONE
案例也不正确。使用
(“a”,“a”,“a”])
(“a”,“b”])
进行测试。它对(“a”,“b”])很有效,但对(“a”,“a”,“a”])不起作用,实际上很好,因为练习表明列表中的元素不会重复。好吧,我的错。下次我会说得更准确,这是不对的。为什么要删除递归并将其替换为
SOME
?您的
NONE
案例也不正确。使用
(“a”,“a”,“a”])
(“a”,“b”])
进行测试。它对(“a”,“b”])很有效,但对(“a”,“a”,“a”])不起作用,实际上很好,因为练习表明列表中的元素不会重复。好吧,我的错。下次“所有元素都是您寻找的”(即成功)与“未找到您的元素”(失败)不同时,我会更准确地说。正如你自己所注意到的,一个简单的列表不能表达差异。对,所以我质疑被告知一个列表是空的,因为它一开始是空的(“所有(不存在的)元素都是你寻找的元素”)是否有用。也许有一个比这个更简单的搜索函数,它不只是返回输入的子列表。我可以想到一些问题,其中int list选项是返回类型,例如“返回精确的更改”任务,即查找给定的一组硬币和一些回现金额,以及一些(可能最少)加在回现金额上的硬币。在这种情况下,
SOME[]
表示“存在一个0硬币的解决方案。”“所有元素都是您查找的元素”(即成功)与“您的元素未找到”(失败)不同。正如你自己所注意到的,一个简单的列表不能表达差异。对,所以我质疑被告知一个列表是空的,因为它一开始是空的(“所有(不存在的)元素都是你寻找的元素”)是否有用。也许有一个比这个更简单的搜索函数,它不只是返回输入的子列表。我可以想到int list选项是返回类型的问题,