2012-03-15 22 views
1

我试图做一个函数在标准的ML,需要2个参数,并返回一个布尔,和2参数可以是任何类型,在规范中它被写为'a * 'a -> bool,但每当我尝试它,它使2参数自动整理。我怎样才能让这个函数有2个参数类型'a。在Standard ML中,如何定义'a *'a - > bool类型的函数?

以下是函数香港专业教育学院一直在努力执行:

fun lessThan (a, b) = 
    if a < b then true 
    else false; 

但是写上述功能之后我得到的是:

val lessThan = fn : int * int -> bool 

,我想这是什么:

val lessThan = fn : 'a * 'a -> bool 

我能做些什么来使它工作?

回答

6

如果要使函数终止并返回一个值,Standard ML只有两个函数'a * 'a -> bool。它们是

fun ktrue (_, _) = true 
fun kfalse (_, _) = false 

所有其他总,该类型的纯函数是从上述两个不可区分的。

而这两个功能其实有更一般的型号'a * 'b -> bool

这实际上是编程语言理论的一个相当深入的结果。如果你想学习基础知识,你可以尝试阅读John Reynolds关于表征独立性的工作或者Phil Wadler关于“自由定理”的着作。

+1

良好的评论,和(很明显)是一个美丽的论文,但我认为对于OP的问题,这个问题更多的是与操作符被单独定义在整数。 (不是说这个回应也不值得一些想法,它当然可以!) – 2012-03-18 08:47:01

+1

顺便说一句,如果你提到它(@aizen),Ramsey博士的参考文献是“自由定理”真正令人敬畏的阅读给任何人! – 2012-03-18 08:53:04

0

我相信这是我们可以用SML中的函数来解决的那类问题。

例如,考虑一个名为TOTALORDER的签名的存在,它在问题中定义了你的函数(lt表示低于)。

signature TOTALORDER = 
sig 
    type element 
    val lt: element * element -> bool 
end 

正如你可以看到函数定义为element * element -> bool,和元素的类型在这里不明确的。

然后我们就可以定义TOTALORDER的两种不同的实现与不同类型的工作,具体如下:

structure String : TOTALORDER = 
struct 
    type element = string 
    fun lt(a:string, b) = a < b 
end 

structure Integer: TOTALORDER = 
struct 
    type element = int 
    fun lt(a, b) = a < b 
end 

上面我们已经定义了工作能力字符串的实现,而另一个能够与整数工作。你可以看到在这些实现中我们定义了什么是element的实际类型。

现在,我们可以定义互换类型的仿函数的魔力,具体如下:

functor MakeComparator(Lt: TOTALORDER): 
    sig 
     val descending : Lt.element * Lt.element -> Lt.element * Lt.element 
     val ascending : Lt.element * Lt.element -> Lt.element * Lt.element 
    end 
    = 
    struct 
     open Lt; 

     fun descending(a,b) = if lt(a,b) then (b,a) else (a,b) 
     fun ascending(a,b) = if lt(a,b) then (a,b) else (b,a) 
    end 

在这里,我们可以看出,仿函数定义包含两个函数调用上升和下降的基础上,我们TOTALORDER签名定义。仿函数作为参数接收这种签名的实现。后来它使用它,在结构实现中按照升序或降序排序一对。

因此,最终,a和b的类型取决于提供给函子的TOTALORDER的实现中元素的类型。

现在,我们可以使用不同的比较类型如下创建不同的实现:

structure StringComparator = MakeComparator(String) 
structure IntegerComparator = MakeComparator(Integer) 

,我们可以与他们的类型相应地使用它们。例如:

val res01 = StringComparator.ascending("arm","house") (*(arm,house)*) 
val res02 = StringComparator.descending("arm","house") (*(house,arm)*) 
val res03 = IntegerComparator.ascending(1,2) (*(1,2)*) 
val res04 = IntegerComparator.descending(1,2) (*(2,1)*) 

这当然是冗长的,相对于其他语言,如Haskell的类型类,但我认为这是解决问题的有效方法。

相关问题