当我只有datatype Nt = int | string,sml不抱怨.但是当我也有val n = 6 : Nt,ml不接受6作为Nt.为什么是这样?我知道,通常应该有数据之前建设者int和string,但在这里我具有定义,可以采取两种功能int或string.
你误解了代码.需要说明的是,如果没有构造函数,则无法定义数据类型.但是ML对于类型和值有不同的名称空间.的出现int和string在你的例子是价值的标识符.因此,它们只是定义了新的nullary构造函数,并且与同名的类型完全无关.你现在可以定义val n = int : Nt.就像你写的一样datatype Nt = foo | bar.
拥有可以采用int或字符串的函数可以用两种方式解释.你可能意味着你想要一个可以接受任何东西并且做一些通用的函数 - 这将是一个多态函数.例如
fun id x = x
Run Code Online (Sandbox Code Playgroud)
可以同时使用整数和字符串并返回它们,但不会对它们的内容进行特定的处理.如果你想要一个可以取一个int或一个字符串的函数并做一些与它们不同的函数,根据你有哪个输入,你可以使用一个union类型,例如
datatype Nt = Int of int (* constructor has the type int -> Nt *)
| Str of string (* constructor has the type string -> Nt *)
val sample_1 = Int 42
val sample_2 = Str "Hello"
Run Code Online (Sandbox Code Playgroud)
在这里,Int并且Str是值构造像职能的工作中,他们分别取类型为int /字符串的值,作为参数和返回工会键入NT值.我将它们命名为除了以外的东西int并string表示值构造函数与int和string类型不同.如果他们没有参与论证,他们唯一的用途就是区分彼此(在这种情况下,他们将与true/ 同构false).
将这样的值作为输入的函数必须与具有相同名称的模式构造函数匹配.以下是一些将此union类型作为参数的函数:
fun isAnInt (Int i) = true
| isAnInt (Str s) = false
fun intVal (Int i) = i
| intVal (Str i) = 0
fun strVal (Int i) = Int.toString i
| strVal (Str s) = s
fun sumNt [] = 0
| sumNt (x::xs) = intVal x + sumNt xs
fun concatNt [] = ""
| concatNt (x::xs) = strVal x ^ concatNt xs
Run Code Online (Sandbox Code Playgroud)
这里正在测试这些功能:
val test_isAnInt_1 = isAnInt sample_1 = true
val test_isAnInt_2 = isAnInt sample_2 = false
val test_intVal_1 = intVal sample_1 = 42
val test_intVal_2 = intVal sample_2 = 0
val test_strVal_1 = strVal sample_1 = "42"
val test_strVal_2 = strVal sample_2 = "Hello"
val test_sumNt_1 = sumNt [] = 0
val test_sumNt_2 = sumNt [sample_1, sample_1, sample_2, sample_1] = 126
val test_sumNt_3 = sumNt [sample_2, sample_2, sample_2] = 0
val test_concatNt_1 = concatNt [] = ""
val test_concatNt_2 = concatNt [sample_1, sample_1, sample_1] = "424242"
val test_concatNt_3 = concatNt [sample_1, sample_2, sample_1] = "42Hello42"
Run Code Online (Sandbox Code Playgroud)