可以使用以下多态函数
let id x = x;;
let compose f g x = f (g x);;
let rec fix f = f (fix f);; (*laziness aside*)
是为类型/类型构造函数或模块/函子编写的吗?我试过了
type 'x id = Id of 'x;;
type 'f 'g 'x compose = Compose of ('f ('g 'x));;
type 'f fix = Fix of ('f (Fix 'f));;
表示类型,但不起作用。
这是类型的Haskell版本:
data Id x = Id x
data Compose f g x = Compose (f (g x))
data Fix f = Fix (f (Fix f))
-- examples:
l = Compose [Just 'a'] :: Compose [] Maybe Char
type Natural = Fix Maybe -- natural numbers are fixpoint of Maybe
n = Fix (Just (Fix (Just (Fix Nothing)))) :: Natural -- n is 2
-- up to isomorphism composition of identity and f is f:
iso :: Compose Id f x -> f x
iso (Compose (Id a)) = a
答案 0 :(得分:32)
Haskell允许更高类型的类型变量。 ML方言,包括Caml,只允许类型变量“*”。翻译成普通英语,
在Haskell中,类型变量g
可以对应于“类型构造函数”,如Maybe
或IO
或列表。因此,如果例如g x
为g
且Maybe
为x
,则Haskell示例中的Integer
就可以了(行话:“良好的”)。
在ML中,类型变量'g
只能对应int
或string
这样的“地面类型”,而不能对应option
之类的类型构造函数或list
。因此,尝试将类型变量应用于其他类型时,永远不会正确。
据我所知,ML的这种限制没有深层原因。最可能的解释是历史偶然性。当米尔纳最初提出他关于多态性的观点时,他使用了非常简单的类型变量,只代表了类型的单型*。 Haskell的早期版本做了同样的事情,然后在某些时候,Mark Jones发现推断类型变量的种类实际上非常容易。 Haskell很快被修改为允许更高类型的变量,但ML从未赶上。
INRIA的人们对ML做了很多其他的改变,我有点惊讶他们从来没有做过这个。当我用ML编程时,我可能喜欢使用更高级的变量。但它们不在那里,除了使用functors之外,我不知道如何编码你正在谈论的那些例子。
答案 1 :(得分:21)
您可以在OCaml中执行类似的操作,使用模块代替类型,使用仿函数(高阶模块)代替高阶类型。但它看起来更加丑陋而且它没有类型推理能力,所以你必须手动指定很多东西。
module type Type = sig
type t
end
module Char = struct
type t = char
end
module List (X:Type) = struct
type t = X.t list
end
module Maybe (X:Type) = struct
type t = X.t option
end
(* In the following, I decided to omit the redundant
single constructors "Id of ...", "Compose of ...", since
they don't help in OCaml since we can't use inference *)
module Id (X:Type) = X
module Compose
(F:functor(Z:Type)->Type)
(G:functor(Y:Type)->Type)
(X:Type) = F(G(X))
let l : Compose(List)(Maybe)(Char).t = [Some 'a']
module Example2 (F:functor(Y:Type)->Type) (X:Type) = struct
(* unlike types, "free" module variables are not allowed,
so we have to put it inside another functor in order
to scope F and X *)
let iso (a:Compose(Id)(F)(X).t) : F(X).t = a
end
答案 2 :(得分:0)
嗯......我不是高阶类型的专家,也不是Haskell编程的专家。 但是对于F#(这是OCaml)来说这似乎没问题,你能用这些吗?
type 'x id = Id of 'x;;
type 'f fix = Fix of ('f fix -> 'f);;
type ('f,'g,'x) compose = Compose of ('f ->'g -> 'x);;
我把最后一个包裹在元组中,因为我没有想出更好的东西......
答案 3 :(得分:-1)
你可以做到,但你需要做一些技巧:
newtype Fix f = In{out:: f (Fix f)}
您可以在之后定义Cata:
Cata :: (Functor f) => (f a -> a) -> Fix f -> a
Cata f = f.(fmap (cata f)).out
这将为所有仿函数定义一个通用的catamorphism,您可以使用它来构建自己的东西。例如:
data ListFix a b = Nil | Cons a b
data List a = Fix (ListFix a)
instance functor (ListFix a) where
fmap f Nil = Nil
fmap f (Cons a lst) = Cons a (f lst)