数据类型Nt = int | ML中的字符串

时间:2015-11-13 01:36:18

标签: sml ml

当我只有datatype Nt = int | string时,sml并没有抱怨。但是当我也有val n = 6 : Nt时,ml并不接受6作为Nt。为什么是这样?我知道,通常在intstring之前应该有数据构造函数,但是我在这里定义了可以采用int或{{1}的函数}。

2 个答案:

答案 0 :(得分:9)

您误解了代码。需要说明的是,如果没有构造函数,则无法定义数据类型。但是ML对于类型和值有不同的名称空间。您的示例中出现的intstring是值标识符。因此,它们只是定义了新的nullary构造函数,并且与同名的类型完全无关。您现在可以定义val n = int : Nt。就好像你写了datatype Nt = foo | bar

答案 1 :(得分:5)

具有可以采用int或字符串的函数可以用两种方式解释。你可能意味着你想要一个可以接受任何东西并且做一些通用的函数 - 这将是一个多态函数。 E.g。

fun id x = x

可以同时使用整数和字符串并返回它们,但不会对其内容进行特定的处理。如果你想要一个可以接受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"

这里,IntStr值构造函数,它们的功能与函数类似,它们分别将int / string类型的值作为参数并返回一个值联合类型Nt。我将它们命名为intstring之外的其他内容,以表示值构造函数与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

这里正在测试这些功能:

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"