我写了一个程序,它在列表中包含列表的整数并将它们加在一起。现在我想再次编写这个函数,但是使用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的变体时,我得到操作数并不同意错误。
答案 0 :(得分:0)
有点不清楚选项的目的是什么;你想在 int选项列表中添加数字吗?例如。 [SOME 1, SOME 2, NONE, SOME 3]
。甚至 int选项列表?例如。 [[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选项< / em>因为fold2
的基本情况,并且出于同样的原因返回'b选项。但是,add2
的类型为
int -> int -> int option
您可以执行以下操作之一来解决此问题:
您的add2
假设其操作数是整数,而不是整数选项;即你正在写SOME (x + y)
,而你只能在数字时添加x
和y
。根据您正在做的事情,add2
可以将其操作数视为可选操作; e.g。
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)
为NONE
或SOME 0
的情况下,它们会有所不同。
fold2
在SOME
周围总是包围x
的意义上是有点无意义的:如果总是,然后为什么要这样做?您可以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
并且您创建了一种特殊类型的折叠,同时丢弃NONE
个。我可能更喜欢有一个单独的功能,并将其与常规折叠结合使用:
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)
但是,这完全取决于你想要完成的事情。