Modules of the first class with parametric types (constructor of type Ff escaped its scope)

I am currently playing with modules to see how they can be used by similar Haskell class classes. I'm currently trying to play with a functor type class:

module type Functor =
   sig
      type 'a f
      val fmap : ('a -> 'b) -> ('a f -> 'b f)
   end


module IdFunc =
   struct
      type 'a f  = Id of 'a
      let fmap f = fun (Id a) -> Id (f a)
      let runId  (Id a) = a
   end

let outmap (module F : Functor) av = F.fmap f av

However, in this case outmapit will not be typed correctly, the compiler will produce an error The type constructor F.f would escape its scope. I know why this error occurs in this case, but I'm not sure how to get around it (since the parameter f is parameterized).

I have already tried using locally abstract types:

let outmap (type s) (module F : Functor with type 'a f = s) f av = F.fmap f av

or

let outmap (type a) (type b) (type fa) (type fb) 
 (module F : Functor with type a f = fa type b f = fb) f av = 
 F.fmap f av

or

let outmap (type s) (module F : Functor with type f = s) f av = F.fmap f av

which just give me various syntax errors or input errors.

Is there any way around this?

In Haskell, it will be simple:

outmap : Functor f => (a -> b) -> f a -> f b

what would be equivalent in ocaml (if any)?

==== EDIT ====

I found one way to get something similar to work:

module type Functor =
   sig
      type a
      type b
      type af
      type bf
      val fmap : (a -> b) -> (af -> bf)
   end

module type FromTo =
   sig
      type a
      type b
   end

module IdFunc =
   functor (FT : FromTo) -> 
   struct
      type a = FT.a
      type b = FT.b
      type 'a f  = Id of 'a
      type af = a f
      type bf = b f
      let fmap f = fun (Id a) -> Id (f a)
      let runId  (Id a) = a
   end

let outmap (type a') (type b') (type af') (type bf') 
   (module F : Functor 
      with type a  = a'  and
           type b  = b'  and
           type af = af' and
           type bf = bf') 
   f av =  F.fmap f av

module M = IdFunc(struct type a = int type b = string end)

let oi = outmap (module M)

let test = oi (fun _ -> "Test") (M.Id 10)

-, , , .

+4
2

, , , ( ), OCaml.

, OCaml , . 1.1 .

, , outmap , .

( higher - opam), . , , .

+8

(, app Newtype1, , higher opam), :

module type Functor = sig
  type t
  val fmap : ('a -> 'b) -> ('a, t) app -> ('b, t) app
end

module Id = Newtype1(struct type 'a t = 'a end)

module IdFunc : Functor with type t = Id.t = struct
  type t = Id.t
  let fmap f x = x |> Id.prj |> f |> Id.inj
end

let runId (x : ('a, Id.t) app) : 'a = Id.prj x

let outmap (type a)
           (module F : Functor with type t = a)
           f av =
  F.fmap f av

https://github.com/hongchangwu/ocaml-type-classes

+1

Source: https://habr.com/ru/post/1545827/


All Articles