为什么curry foldr with @会产生运算符域错误?

时间:2013-04-26 00:24:10

标签: sml

所以我正在写一个扁平的fn,我明白了:

fun flatten ls = List.foldr op @ [] ls

我意识到,变量ls的命名应该是不必要的,而我可能只是在paritally应用foldr。但这打破了:

val flatten = List.foldr op @ []
是什么让它搞砸了?我似乎必须推断出fun声明和部分应用foldr typ

类似的求和函数有效,这让我想知道为什么@特别不起作用:

val sum = List.foldr op + 0

编辑:我收到的错误:

- val flatten = List.foldr op @ [];

stdIn:1.6-2.13 Warning: type vars not generalized because of
   value restriction are instantiated to dummy types (X1,X2,...)
val flatten = fn : ?.X1 list list -> ?.X1 list

- flatten [[1], [1]];

stdIn:3.1-3.19 Error: operator and operand don't agree [literal]
  operator domain: ?.X1 list list
  operand:         int list list
  in expression:
    flatten ((1 :: nil) :: (1 :: nil) :: nil)

2 个答案:

答案 0 :(得分:3)

我有点不清楚你指的是什么错误。您在标题中提到您收到“操作员域错误”,但是您的代码只会产生“值限制”警告。有很大的不同。

价值限制是让你了解的更复杂的事情之一,但实质上它是在语言中引用时保留类型安全的。

MLton wiki在value restriction上有一篇很棒的文章,其中涵盖了为什么存在价值限制,不必要的拒绝程序,价值限制的替代方案以及如何使用价值限制。

答案 1 :(得分:1)

AJ, Jesper的文章既解释了您所看到的警告,又具有洞察力,但为了解决您的问题,您可能想尝试这样做:

val flatten = foldr op @ ([]:int list);

我认为应该解决你的问题。

编辑:我选择了int list作为显式类型,因为我观察了您的警告消息的性质,并从那里推断出,int list就是您所需要的。 [=

注意:上述解决方案会破坏多态性并将输入限制为所选类型。