Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SML警告:当使用空列表或无选项时,类型变量不是通用的_Sml_Smlnj - Fatal编程技术网

SML警告:当使用空列表或无选项时,类型变量不是通用的

SML警告:当使用空列表或无选项时,类型变量不是通用的,sml,smlnj,Sml,Smlnj,我一辈子都搞不明白为什么下面的SML函数会在我的作业问题中发出警告: fun my_func f ls = case ls of [] => raise MyException | head :: rest => case f head of SOME v => v | NONE => my_func f rest fun f a = if isSome a then a

我一辈子都搞不明白为什么下面的SML函数会在我的作业问题中发出警告:

fun my_func f ls  = 
  case ls of 
  [] => raise MyException
  | head :: rest => case f head of 
                    SOME v => v
                    | NONE => my_func f rest

fun f a = if isSome a then a else NONE;
每当我使用以下测试函数调用我的函数时:

my_func f [NONE, NONE];
my_func f [];
我总是得到警告:

警告:类型变量未通用化,因为 值限制被实例化为虚拟类型(X1、X2、…)

每当我传入至少包含一个SOME值的选项列表时,不会抛出此警告。我知道这一定与我在函数curry中使用多态性有关,但我一直完全不知道如何消除这些警告

如果您有任何想法,请帮助-提前感谢您

警告中引用的值限制是SML中需要理解的比较棘手的事情之一,但是我将尽力解释为什么会出现这种情况,并尝试向您介绍一些资源以了解更多信息

正如您所知,SML将使用类型推断来推断程序中的大多数类型。在此程序中,
my_func
的类型将被推断为
('a->'b选项)->'a list->'b
。正如你所注意到的,这是一种多态类型。当你像这样调用我的函数时

myfunc f [NONE, SOME 1, NONE];
。。。类型变量
'a
'b
被实例化为
int选项
int

但是,当您调用它时,没有上面的
SOME 1这样的值

myfunc f [NONE, NONE];
您认为类型变量应该实例化为什么?这些类型应该是多态的——类似于所有类型的
't
't选项和
't
。但是,有一个限制,它阻止像这样的值采用多态类型

SML将一些表达式定义为非扩展值,并且只有这些值可以采用多态类型。它们是:

  • 文字(常量)
  • 变数
  • 函数表达式
  • 构造函数(除了
    ref
    )应用于非扩展值
  • 带有类型注释的非扩展值
  • 元组,其中每个字段都是非扩展值
  • 每个字段都是非扩展值的记录
  • 列出每个字段是非扩展值的位置
所有其他表达式,尤其是函数调用(这就是对
my_func
的调用)不能是多态的。参考资料也不能。您可能会好奇地发现以下情况并没有引起警告:

 fn () => my_func f [NONE, NONE];
相反,推断的类型是
unit->'a
。但是,如果调用此函数,则会再次收到警告

我对这个限制的原因的理解有点弱,但我相信潜在的根本问题是可变引用。下面是我从MLton网站上获取的一个例子,链接如下:

val r: 'a option ref = ref NONE
val r1: string option ref = r
val r2: int option ref = r
val () = r1 := SOME "foo"
val v: int = valOf (!r2)
由于值限制,此程序不在SML下进行类型检查。如果没有值限制,此程序在运行时将出现类型错误

正如我所说,我的理解是不稳定的。然而,我希望我已经对你遇到的问题有了一点了解,尽管我相信在你的情况下,你可以安全地忽略这个警告。如果您决定更深入地挖掘,以下是一些参考资料:

(顺便说一句,MLton网站是纯金的。这里隐藏的东西太多了,所以如果你想了解SML的一些奇怪之处,我强烈建议你在这里搜索,因为你可能会发现比你最初想要的多得多)

因为看起来您实际上使用的是SML/NJ,所以这是一个非常方便的指南,它将在编译时为您提供错误消息和警告:


非常感谢您的及时回复!我将查看您建议的资源以进行进一步研究,如果我找到解决此警告消息的方法,我将向您报告。正如您所说的,由于其多态性,对于那些空的或不包含任何内容的特定测试用例可能是不可能的。再次感谢你的帮助。没问题,很高兴我能帮忙。要删除警告,您可以做以下几件事:(1)使用任何类型进行注释,这使值不再是多态的:
(my_func f[NONE,NONE]):int
或(2)意识到只有在REPL中输入这样的值时,才会出现此警告,可能不会在调用其他数据的大型程序中出现。Haskell是否有这种奇怪的版本,或者是缺少可变引用保存了它?我不认为这完全是一回事,但Haskell有“单态限制”。。。我不太了解哈斯凯尔,也不太了解其中的微妙之处,不知道他们是否真的有关联。我认为这与懒惰有更大的关系,可以关闭,所以我猜这只是表面上的关系。