如何从数据类型列表中获取数据?
我在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
如何分割列表的头部?我怎样才能拿到钥匙?
答案 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