4 ms·
OCaml functors are not the same as Haskell/F# functors/applicatives (which are essentially one and the same in OCaml if you use named arguments). Instead, they
by mc10 6y ago
OCaml functors are not the same as Haskell/F# functors/applicatives (which are essentially one and the same in OCaml if you use named arguments).
Instead, they're roughly "functions from modules to modules": https://dev.realworldocaml.org/functors.html https://dev.realworldocaml.org/functors.html. Functors allow you to replicate much of what classes/objects in an OO language offer, but with static instead of dynamic dispatch.
- ojnabieoot 6y agoI am an F# person rather than OCaml and am not familiar with the compiler, but this seems to be overstating the difference: I thought the OCaml functors are “real” mathematical functors that implemented a structured type polymorphism over the “input type” - they look pretty similar to C++ templates superficially but they work similarly to Haskell type classes. They are “functions from modules to modules” but those functions take types as values. Real experts should let me know if I am mistaken: I don’t think OCaml and Haskell have strictly the same type system, but they are both similarly more expressive than F# because of this specific type -> type polymorphism that in particular lets you do type-checked monads, etc.
- didibus 6y agoNeither Haskell's nor OCaml's functors are the same as the mathematical one I believe, but both are similar in some way that the word makes sense to be used for their respective feature. In OCaml, functors map between an abstract module and some concrete one. And in Haskell functors are structures that can have a function that maps over their elements. In math a functor is a map between categories. So you can see how all three kinda make sense as functors, but also are different in exactly what they are.
- tome 6y agoBoth Haskell's and OCaml's functors are special cases of the general mathematical one.
- sweeneyrod 6y agoHow? What are the categories that OCaml's Hashtbl.Make maps between? What are the morphisms in those categories and how are they mapped?
- tome 6y agoIt maps between a category with HashedType implementations as objects and a category with Make implementations as objects. Unfortunately it's not a very interesting functor because to satisfy the functor laws I think the categories have to be discrete. It's basically a function! (And functions are indeed a special case of functors.) https://caml.inria.fr/pub/docs/manual-ocaml/libref/Hashtbl.Make.html https://caml.inria.fr/pub/docs/manual-ocaml/libref/Hashtbl.M...
- sweeneyrod 6y agoRight, in other words it is just a function. I don't think the categories have to be discrete just to satisfy the functor laws; even ignoring that, what would the morphisms be in principle? I don't think there is an obvious choice, at least. I think in OCaml, "functor" basically just means "like a function but for modules". They might technically be categorical functors, but it seems quite different to the meaning in Haskell where they are plainly categorical functors (modulo Hask technically not being a category).
- tome 6y agoAgreed, I'm not sure it's a terribly interesting functor.
- Iceland_jack 6y agoHere is one way one might implement a categorical Functor (https://www.reddit.com/r/haskell/comments/eoo16m/base_category_polymorphic_functor_and_functorof/ https://www.reddit.com/r/haskell/comments/eoo16m/base_catego...). A function S -> T maps a S(ource) type to a T(arget) type, like FunctorOf (-S>) (-T>) does between the source category (-S>) and target category (-T>) type Functor :: forall (s :: Type) (t :: Type). (s -> t) -> Constraint class (Category (Src f), Category (Tgt f)) => Functor (f :: s -> t) where type Src (f :: s -> t) :: Cat s type Tgt (f :: s -> t) :: Cat t fmap :: Src f a1 a2 -> Tgt f (f a1) (f a2) type FunctorOf :: forall (s :: Type) (t :: Type). Cat s -> Cat t -> (s -> t) -> Constraint type FunctorOf src tgt f = (Functor f, Src f ~ src, Tgt f ~ tgt) The usual endofunctor type EndofunctorOf :: forall (ob :: Type). Cat ob -> (ob -> ob) -> Constraint type EndofunctorOf @ob cat f = FuntorOf @ob @ob cat cat f we have in Haskell can be defined as FunctorOf @Type @Type (->) (->), or type OldFunctor :: (Type -> Type) -> Constraint type OldFunctor f = EndofunctorOf @Type (->) f