折叠 int 选项函数

fold int option function

我编写了一个程序,将列表中的列表整数相加。现在我试图再次编写此函数,但改用 int option integers。

我从

更改了我原来的功能
fun fold f base [] = base
  | fold f base (x::rest) = f x (fold f base rest);
fun add x y = x+y;
fun sumList L = fold add 0 L;

fun fold2 f base [] = SOME(base)
  | fold2 f base (x::rest) = f (SOME x) (fold2 f base rest);
fun add2 x y = SOME (x + y);
fun sumList2 L = fold2 add2 NONE L;

add 和 fold2 函数都可以编译,但是当我尝试 运行 sumList2 的变体时,出现操作数不一致错误。

有点不清楚这些选项的用途;您要在 int 选项列表 中添加数字吗?例如。 [SOME 1, SOME 2, NONE, SOME 3]。甚至 int option list lists?例如。 [[SOME 1, NONE], [NONE, SOME 2, SOME 3], [], [NONE, NONE, NONE]]。或者您是否尝试在不包含可选值的列表上使用可选类型编写折叠?

你的问题出在f的参数类型上。在fold2中可以推断出有类型

'a option -> 'b option -> 'b option

因为第一个参数总是(SOME x),类型为'一个选项,第二个参数总是(fold2 f base rest),类型为'b option 因为 fold2 的基本情况,和 returns 'b option 出于同样的原因。但是,您的 add2 类型为

int -> int -> int option

您可以执行以下操作之一来解决此问题:

  • 你的add2假定它的操作数是整数,而不是整数选项;也就是说,您正在写 SOME (x + y),并且当它们只是数字时,您只能添加 xy。根据您正在做的事情,add2 可以将其操作数视为可选的;例如

    fun add2 NONE b = b
      | add2 a NONE = a
      | add2 (SOME x) (SOME y) = SOME (x + y)
    

    会将 NONE 视为 0。例如

    fun add2 a b = SOME (Option.getOpt (a, 0) + Option.getOpt (b, 0))
    

    但在 add2 (NONE, NONE)NONESOME 0 的情况下它们会有所不同。

  • 你的 fold2 有点毫无意义,因为它总是在 x 周围包裹一个 SOME:如果那是 always 既然如此,那又何必呢?您可以让 fold2 负责丢弃 NONE,例如

    fun fold2 f base [] = base
      | fold2 f base (NONE::rest) = fold2 f base rest
      | fold2 f base (SOME x::rest) = f x (fold2 f base rest)
    

    在这种情况下它的类型变成

    ('a -> 'b -> 'b) -> 'b -> 'a option list -> 'b
    

    并且您创建了一种特殊的折叠,同时丢弃 NONEs。我可能更喜欢有一个单独的函数来执行此操作并将其与常规折叠结合使用:

    fun fold f base [] = base
      | fold f base (x::rest) = f x (fold f base rest)
    
    fun somes [] = []
      | somes (NONE::xs) = somes xs
      | somes (SOME x::xs) = x::somes xs
    
    fun curry f x y = f (x, y)
    
    fun sumListOption xs = fold (curry op+) 0 (somes xs)
    

不过,这完全取决于您要实现的目标。