在学习环境中,为功能提供类型签名的选项有哪些?
标准ML没有像Haskell这样的顶级类型签名。这是我考虑过的替代方案:
模块签名,它们需要一个单独的签名文件,或者在与模块本身相同的文件中的一个单独的块中定义的类型签名。这就要求使用模块,并且在任何生产系统中都是明智的选择。
当替代方案是单个函数定义时,模块在存根文件中似乎有些冗长。他们俩都介绍了模块的概念,也许有点早,
使用val
和val rec
可以在一行中包含完整的类型签名:
val incr : int -> int =
fn i => i + 1
val rec map : ('a -> 'b) -> 'a list -> 'b list =
fn f => fn xs => case xs of
[] => []
| x::ys => f x :: map f ys
我可以同时使用fun
吗?
如果可能的话,我似乎无法正确理解语法。
当前的解决方案是像这样嵌入参数类型和结果类型:
fun map (f : 'a -> 'b) (xs : 'a list) : 'b list =
raise Fail "'map' is not implemented"
但是我经历过,这种语法给ML新手以一种印象,即解决方案不能或不应该更新为模型解决方案:
fun map f [] = []
| map f (x::xs) = f x :: map f xs
然后看来,应该帮助学生的类型签名可以防止它们进行模式匹配。我不能说这是因为他们认为不能删除类型签名还是应该删除它们。当然,他们是否应该(以及在何处)是样式问题,但是应该使学生能够探索类型推断的样式。
答案 0 :(得分:2)
通过使用let或局部绑定函数以及阴影 您可以声明该函数,然后将其分配给一个值。
为此使用local更为方便,因为它具有以下形式: decl 结尾的本地 decl ,而不是 expr 结尾的 decl 意思是让我们 expr 想要一个顶级参数 f
val map = fn f => let fun map = ... in map end
我不相信人们通常使用 local ,主要是因为模块可以完成local可以做的任何事情,甚至更多,但是当您不使用模块时,也许值得将其视为匿名模块还想解释模块。
local
fun map (f : 'a -> 'b) (x::rest : 'a list) : 'b list
= f x :: map f rest
| map _ ([]) = []
in
val (map : ('a -> 'b) -> 'a list -> 'b list) = map;
end
然后,当需要解释模块时,您可以在局部内部,所有声明周围声明结构, 然后删除本地变量,并尝试解决一种情况,即他们已经编码了2个函数,更合适的是用1个结构替换2个本地变量。
local
structure X = struct
fun id x = x
end
in val id = X.id
end
也许用以下类似的东西开始它们:
exception ReplaceSorryWithYourAnswer
fun sorry () = raise ReplaceSorryWithYourAnswer
local
(* Please fill in the _'s with the arguments
and the call to sorry() with your answer *)
fun map _ _ = sorry ()
in
val map : ('a -> 'b) -> ('a list) -> ('b list) = map
end