Types 在标准ML中,如何定义类型为';a*';a->;布尔?

Types 在标准ML中,如何定义类型为';a*';a->;布尔?,types,parameters,sml,smlnj,ml,Types,Parameters,Sml,Smlnj,Ml,我试图在标准ML中创建一个函数,它接受两个参数并返回一个bool,这两个参数可以是任何类型,在规范中,它被写为'a*'a->bool,但每当我尝试它时,它会自动生成两个参数int。如何使函数接受2个“a”类型的参数 以下是我一直试图实现的功能: fun lessThan (a, b) = if a < b then true else false; 我想要的是: val lessThan = fn : 'a * 'a -> bool 如何使其工作?如果希望函数终

我试图在标准ML中创建一个函数,它接受两个参数并返回一个bool,这两个参数可以是任何类型,在规范中,它被写为
'a*'a->bool
,但每当我尝试它时,它会自动生成两个参数int。如何使函数接受2个“a”类型的参数

以下是我一直试图实现的功能:

fun lessThan (a, b) = 
    if a < b then true
    else false;
我想要的是:

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

如何使其工作?

如果希望函数终止并返回值,标准ML只有两个类型为
'a*'a->bool
的函数。是的

fun ktrue  (_, _) = true
fun kfalse (_, _) = false
这种类型的所有其他全部纯函数与上述两个函数无法区分

这两个函数实际上具有更一般的类型
'a*'b->bool


这实际上是编程语言理论的一个相当深刻的结果。如果你想学习基础,你可以阅读约翰·雷诺兹关于表示独立性的著作或菲尔·瓦德勒关于“自由定理”的著作。

如果你想让函数终止并返回一个值,标准ML只有两个
'a*'a->bool
类型的函数。是的

fun ktrue  (_, _) = true
fun kfalse (_, _) = false
这种类型的所有其他全部纯函数与上述两个函数无法区分

这两个函数实际上具有更一般的类型
'a*'b->bool


这实际上是编程语言理论的一个相当深刻的结果。如果你想学习基础,你可以尝试阅读约翰·雷诺兹(John Reynolds)关于表示独立性的著作或菲尔·瓦德勒(Phil Wadler)关于“自由定理”的著作。

我相信这是我们可以用SML中的函子解决的问题

例如,考虑存在一个名为ToalOrror的签名,它定义了问题中的函数(LT意义小于)。

如您所见,函数定义为
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
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
structure StringComparator = MakeComparator(String)
structure IntegerComparator = MakeComparator(Integer)
在这里我们可以看到,函子根据TOTALORDER定义,用两个函数定义了一个签名,分别称为升序和降序。函子作为参数接收此类签名的实现。后来,在struc实现中,它使用它按升序或降序对一对进行排序

因此,a和b的类型最终取决于提供给函子的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
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
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等具有类型类的其他语言相比,它肯定是冗长的,但我相信它是解决这个问题的有效方法

我相信这是我们可以用SML中的函子来解决的问题

例如,考虑存在一个名为ToalOrror的签名,它定义了问题中的函数(LT意义小于)。

如您所见,函数定义为
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
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
structure StringComparator = MakeComparator(String)
structure IntegerComparator = MakeComparator(Integer)
在这里我们可以看到,函子根据TOTALORDER定义,用两个函数定义了一个签名,分别称为升序和降序。函子作为参数接收此类签名的实现。后来,在struc实现中,它使用它按升序或降序对一对进行排序

因此,a和b的类型最终取决于提供给函子的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
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
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的问题,问题更多地与运算符仅在int上定义有关。(不是说这个回答也不值得思考,它当然值得!)顺便说一句,如果你提到它(@aizen),拉姆齐博士的论文引用的是“免费定理”,对任何人来说都是非常棒的读物!好的评论,(显然)是一篇漂亮的论文,但我认为对于OP的问题,问题更多地与运算符仅在int上定义有关。(不是说这个回答也不值得思考,它当然值得!)顺便说一句,如果你提到它(@aizen),拉姆齐博士的论文引用的是“免费定理”,对任何人来说都是非常棒的读物!