【问题标题】:fold int option functionfold int 选项函数
【发布时间】:2018-07-29 05:59:32
【问题描述】:

我编写了一个程序,它接受列表中的整数并将它们相加。现在我正在尝试再次编写此函数,但改用 int 选项整数。

我改变了我原来的功能

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 的变体时,我得到操作数不同意错误。

【问题讨论】:

    标签: polymorphism sml fold


    【解决方案1】:

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

    您的问题在于f 的参数类型。在fold2中,可以推断出有类型

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

    因为第一个参数始终为(SOME x),其类型为'a option,第二个参数始终为(fold2 f base rest),其类型为'b option,因为fold2 的基本情况,并出于同样的原因返回 'b 选项。但是,您的 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)
      

      会将NONEs 视为0s。例如,也会如此。

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

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

    • 您的fold2 总是在x 周围包裹SOME,这有点毫无意义:如果总是 是这样,那为什么还要这样做呢?你可以让fold2负责丢弃NONEs,例如

      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)
      

    不过,这完全取决于您要完成的工作。

    【讨论】:

    • 非常感谢,我没有意识到我的问题在于没有正确处理 add2。最终目标是在可能是 [[SOME(1),SOME(2),SOME(3)],[SOME(4),SOME(5)]] 的地方进行加法,但这只是我的第一步折叠,以便我可以将其映射到列表列表。这很有帮助,非常感谢!
    猜你喜欢
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多