1

我在标准 ML 中有以下代码:

datatype a = a;
val x = a;
val y:a = a;
val z = a;

fun fa a = a;

fun not' x = case x of
    true => false
  | false => true;

fun fst (a,b) = a;
fun snd (a,b) = b;

我在 sum 类型 ( not') 上的函数工作得很好,但是当我尝试在产品类型 ( fst) 上使用我的函数时,它给了我这个错误:

- fst (1,2);
! Toplevel input:
! fst (1,2);
!      ^
! Type clash: expression of type
!   int
! cannot have type
!   a
-  

为什么?

4

1 回答 1

1

您需要更加了解变量名称和范围。

发生的事情是您已经声明了具有类型构造函数a和值构造函数的数据类型a。然后,您在and函数中迟到a用作参数,这意味着您正在匹配该数据类型的值构造函数。可能不是你想要的。fstsnda

快速修复只是更改两个函数中使用的变量名称

fun fst (x, y) = x;
fun snd (x, y) = y;

- fst(1,2);
val it = 1 : int

通常问题很容易从类型中看出,但是由于您选择了一个相当不幸的名称来使用,您的函数的原始类型是

val fst = fn : a * 'a -> a
val snd = fn : a * 'a -> 'a

但是当函数被固定为不引用数据类型 a 时,它们将'a改为

val fst = fn : 'a * 'b -> 'a
val snd = fn : 'a * 'b -> 'b

值构造函数以大写字母开头,类型构造函数以全部小写字母开头,通常被认为是一种好的风格。一个例子是选项数据类型,但是它使用所有大写字母作为值构造函数(一些其他语言甚至强制执行此操作)

datatype 'a option = NONE 
                   | SOME of 'a

如果我们将用于类型和值的名称分开,并将其称为“a”以外的其他名称,整个想法可能会更有意义,因为它也用作“第一个”多态类型变量的一部分(即,大多数解释器以'a)。

datatype foo = Bar;
val x = Bar;
val y:foo = Bar;
val z = Bar;

fun fa Bar = Bar;
于 2013-04-02T13:48:34.113 回答