处理数据类型列表

时间:2015-12-17 11:13:52

标签: sml

如何从数据类型列表中获取数据?

我在SML中有一个简单的代码:

datatype (''a, 'b) dict = 
     Nil
   | Dictionary of {key:''a, value:'b} list;

datatype 'dict list =
    nil
  | :: of 'dict * ('dict list);

val d = (Dictionary [{key="hello",value=[1,2]}]);
fun aux ((x::y):{key:''a, value:'b} list) = [x];

我想从列表的头部获取密钥,但我甚至无法将其分开。

当我插入时:

aux d;

我收到了下一个错误:

stdIn:2.1-2.6 Error: operator and operand don't agree [tycon mismatch]
  operator domain: {key:''Z, value:zY} list
  operand:         (string,int ?.list) dict
  in expression:
    aux d

如何分割列表的头部?我怎样才能拿到钥匙?

2 个答案:

答案 0 :(得分:2)

您的第一个数据类型(''a, 'b) dict与内置类型(''a, 'b) list option同构(因为额外的Nil)。

您的第二个数据类型'dict list会遮挡内置类型'a list。请注意,调用类型参数'dict 并不会使它变得特殊。您可能不应该在具体类型后命名,而是将其命名为'a 'key 等。

引用旧'a list的函数和类型(例如您的第一个类型和内置函数)将生成一种依赖于::的新定义的列表和函数, nil将生成另一种类型的列表。这非常令人困惑 - 覆盖内置类型,创建具有唯一类型名称和唯一值构造函数名称的新类型。

您的类型错误来自将(string, int list) dict类型的值提供给期望{key:''a, value:'b} list(新类型列表)的函数。显然,值Dictionary [{key="hello",value=[1,2]}]不是这样的列表。

这是一个使用内置列表的简单字典实现:

structure Dictionary =
struct
    type (''a, 'b) dict = (''a * 'b) list

    fun insert (key, value, []) = [(key, value)]
      | insert (key, value, (key2,value2)::rest) =
          if key = key2
          then (key,value)::rest
          else (key2,value2)::insert (key, value, rest)

    fun lookup (key, []) = NONE
      | lookup (key, (key2,value2)::rest) =
          if key = key2 
          then SOME value2
          else lookup (key, rest)
end

它不使用数据类型,也不会抽象出字典的表示形式。如果你想改进表示,从列表到一种树,你可能需要依赖顺序比较(小于,大于,等于)而不是严格的相等。

答案 1 :(得分:1)

在多态函数定义中解释数据类型定义时,SML似乎有些麻烦。我怀疑问题在于它无法推断定义中Nil的类型。我建议删除该子句并使用数据类型定义:

datatype (''a, 'b) dict = Dictionary of {key: ''a, value: 'b} list;

这样所有词典都是Dictionary模式的实例。如果您需要空字典,函数定义中的基本情况将是模式Dictionary([])Dictionary(Nil)

您需要在函数定义中包含Dictionary构造函数。要从第一个条目中提取密钥,您可以执行以下操作:

fun aux (Dictionary(entries)) = #key(hd(entries));

这使用#运算符从条目列表的头部提取标记为key的字段。您还可以使用更多模式匹配:

fun aux (Dictionary({key = x, value = y}::entries)) = x;

在任何一种情况下,您都可以获得样本数据:

- aux d;
val it = "hello" : string