折叠 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)
,并且当它们只是数字时,您只能添加 x
和 y
。根据您正在做的事情,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)
为 NONE
或 SOME 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
并且您创建了一种特殊的折叠,同时丢弃 NONE
s。我可能更喜欢有一个单独的函数来执行此操作并将其与常规折叠结合使用:
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)
不过,这完全取决于您要实现的目标。
我编写了一个程序,将列表中的列表整数相加。现在我试图再次编写此函数,但改用 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)
,并且当它们只是数字时,您只能添加x
和y
。根据您正在做的事情,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)
为NONE
或SOME 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
并且您创建了一种特殊的折叠,同时丢弃
NONE
s。我可能更喜欢有一个单独的函数来执行此操作并将其与常规折叠结合使用: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)
不过,这完全取决于您要实现的目标。