我可以注释“ fun”声明的完整类型吗?

时间:2018-10-18 12:36:24

标签: functional-programming sml

在学习环境中,为功能提供类型签名的选项有哪些?

标准ML没有像Haskell这样的顶级类型签名。这是我考虑过的替代方案:

  1. 模块签名,它们需要一个单独的签名文件,或者在与模块本身相同的文件中的一个单独的块中定义的类型签名。这就要求使用模块,并且在任何生产系统中都是明智的选择。

    当替代方案是单个函数定义时,模块在存根文件中似乎有些冗长。他们俩都介绍了模块的概念,也许有点早,

  2. 使用valval 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吗?

    如果可能的话,我似乎无法正确理解语法。

  3. 当前的解决方案是像这样嵌入参数类型和结果类型:

    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
    

    然后看来,应该帮助学生的类型签名可以防止它们进行模式匹配。我不能说这是因为他们认为不能删除类型签名还是应该删除它们。当然,他们是否应该(以及在何处)是样式问题,但是应该使学生能够探索类型推断的样式。

1 个答案:

答案 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