我可以注释 `fun` 声明的完整类型吗?
Can I annotate the complete type of a `fun` declaration?
在学习环境中,我有哪些选项可以为函数提供类型签名?
标准 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
看来应该帮助学生的类型签名阻止了他们进行模式匹配。我不能说这是否是因为他们认为类型签名无法删除或不应删除。当然,他们是否应该(以及在哪里)是一个风格问题,但学生应该能够探索类型推断的风格。
通过使用 let 或局部绑定函数,以及阴影
你可以声明函数,然后给它赋值。
为此使用 local 更方便,因为它具有以下形式:
local decl in decl 结束,而不是让 decl in expr结束,
意思是让我们 expr,想要一个顶级参数 f
val map = fn f => let fun map = ... in map end
我不相信人们通常会再使用 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
然后在解释模块的时候,你可以在局部声明结构,围绕所有的声明,
然后去掉local,试着想出一个情况,他们编码了2个函数,用1个结构替换2个local更合适。
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
在学习环境中,我有哪些选项可以为函数提供类型签名?
标准 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
看来应该帮助学生的类型签名阻止了他们进行模式匹配。我不能说这是否是因为他们认为类型签名无法删除或不应删除。当然,他们是否应该(以及在哪里)是一个风格问题,但学生应该能够探索类型推断的风格。
通过使用 let 或局部绑定函数,以及阴影 你可以声明函数,然后给它赋值。
为此使用 local 更方便,因为它具有以下形式: local decl in decl 结束,而不是让 decl in expr结束, 意思是让我们 expr,想要一个顶级参数 f
val map = fn f => let fun map = ... in map end
我不相信人们通常会再使用 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
然后在解释模块的时候,你可以在局部声明结构,围绕所有的声明, 然后去掉local,试着想出一个情况,他们编码了2个函数,用1个结构替换2个local更合适。
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