声明SML中的函数类型

时间:2019-03-02 23:41:56

标签: sml ml

我是ML的新手,但是在其他使用类型推断的语言中,我已经学会了习惯:只要右侧的推断对于人类读者来说是显而易见的,便会忽略事物的类型,并明确声明推断对人类不明显的事物的类型。我喜欢这个约定,并希望在我的ML代码中继续使用它。

我有以下等效的示例函数声明:

fun hasFour      [] = false
  | hasFour (x::xs) = (x = 4) orelse hasFour xs

等同于

val rec hasFour: int list -> bool =
 fn      [] => false
  | (x::xs) => (x = 4) orelse hasFour xs

我喜欢后一种形式,不仅因为我在阅读函数时更容易弄清函数的类型,而且因为它显式声明了函数的类型,因此,如果我在自己的代码中弄错了实施时,不会偶然声明语法上有效但类型错误的东西,以后很难调试。

我的问题是:我想使用fun而不是val rec,因为匿名fn只能接受一个参数。因此,后一种技术对于int -> int -> bool之类的函数在语法上无效。有没有一种方法可以在fun中明确声明类型?还是我在这篇文章中命名了所有首选的替代方法,并且应该仅遵循这些模式之一?我可以发现在显式类型声明中使用fun的唯一方法是向模式中的每个参数添加类型声明,这非常丑陋和可怕,如下所示:

fun hasFour ([]:int list):bool = false
  | hasFour            (x::xs) = (x = 4) orelse hasFour xs

一个同事按照以下模式向我展示了一些代码:

fun hasFour      [] = false
  | hasFour (x::xs) = (x = 4) orelse hasFour xs

val _ = op hasFour: int list -> bool

通过声明一个未命名的变量并将其设置为具有强制类型的函数的实例,我们可以有效地实现所需的结果,但是val _必须出现在完全定义的函数的下面 ,除非您只是习惯了这种模式并学会期望它,否则对人类读者来说,这种情况并不那么明显。

1 个答案:

答案 0 :(得分:0)

最近我问了一个非常相似的问题Can I annotate the complete type of a fun declaration?

您当前的解决方案将是一个很好的答案。

您可以使用带有多个fn的多个咖喱参数,例如喜欢:

val rec member : ''a -> ''a list -> bool =
    fn x => fn [] => false
             | y::ys => x = y orelse member x ys

或者您可以按照当前的方式进行操作,也可以按照哑光提示进行操作:

local
  fun member _ [] = false
    | member x (y::ys) = x = y orelse member x ys
in
  val member = member : ''a -> ''a list -> bool
end

但是使用fun和完整类型签名首先列出的组合仍然难以捉摸。

对于类似于生产的代码,规范是在模块签名中收集类型签名。参见ML for the Working Programmer, ch. 7签名和抽象,第267-268页。虽然我认为您当时想使用Ocaml。