我相信这是我们可以用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的类型类,但我认为这是解决问题的有效方法。
良好的评论,和(很明显)是一个美丽的论文,但我认为对于OP的问题,这个问题更多的是与操作符被单独定义在整数。 (不是说这个回应也不值得一些想法,它当然可以!) – 2012-03-18 08:47:01
顺便说一句,如果你提到它(@aizen),Ramsey博士的参考文献是“自由定理”真正令人敬畏的阅读给任何人! – 2012-03-18 08:53:04