caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Unifying buildt-in types with polymorphic types
@ 2014-05-15 19:24 Peter Frey
  2014-05-15 20:28 ` Jeremy Yallop
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Frey @ 2014-05-15 19:24 UTC (permalink / raw)
  To: caml-list

(* In the code below I have 3 fragments of streams, based on a cons
cell; another on an array and, finally, the third is based on a string.
  I need all streams to have the same signature 'StreamOps'.
  This works fine for a stream where 'a t is a true polymorphic
 value but fails for module StmStr at the bottom of the code   sample;
giving:
       ...
       Values do not match:
         val head : int * 'a cursor -> char
       is not included in
         val head : 'a t -> 'a

I don't know if I run afoul of a form of narrowing; or if this is some
sort of limitation with respect to unboxed types. 

Any help would be greatly appreciated.

Peter Frey
*)


module type StreamOps = sig
  type 'a t 
    val head : 'a t -> 'a
end

module LazyStream : StreamOps = struct 
type 'a t = Cons of 'a * 'a t Lazy.t
  let head (Cons (h, _)) = h
end

module StmLzy = (LazyStream:StreamOps with type 'a t = 'a LazyStream.t)

module MakeEltAry = functor(S:sig include module type of Array end) ->
struct
type 'a cursor = { ofs: int; lim: int; data: 'a array }
 and 'a t = int * 'a cursor 

  let get s i = S.get s.data i 
  let head   (i, s)    = get s i
end

module EltAry = MakeEltAry(Array)
module StmAry = (EltAry:StreamOps with type 'a t = 'a EltAry.t)

module MakeEltStr = functor(S:sig include module type of String end) ->
struct
type 'a cursor = { ofs: int; lim: int; data: string }
 and 'a t = int * 'a cursor 
 
  let get s i = S.get s.data i 
  let head   (i, s)    = get s i
end

module EltStr = MakeEltStr(String)
module StmStr = (EltStr:StreamOps with type 'a t = 'a EltStr.t)






^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] Unifying buildt-in types with polymorphic types
  2014-05-15 19:24 [Caml-list] Unifying buildt-in types with polymorphic types Peter Frey
@ 2014-05-15 20:28 ` Jeremy Yallop
  2014-05-16 21:41   ` Peter Frey
  0 siblings, 1 reply; 3+ messages in thread
From: Jeremy Yallop @ 2014-05-15 20:28 UTC (permalink / raw)
  To: Peter Frey; +Cc: Caml List

On 15 May 2014 20:24, Peter Frey <pjfrey@sympatico.ca> wrote:
> I need all streams to have the same signature 'StreamOps'.

It's not possible with the current definition of StreamOps.  The
difficulty is that the stream type and the element type vary
non-uniformly in your various stream implementations:

   StmLzy defines streams of type 'a t = Cons of 'a * 'a t Lazy.t
                  with elements of 'a

   StmAry defines streams of type 'a t = int * 'a cursor
                  with elements of 'a

   StmStr defines streams of type 'a t = int * 'a cursor
                  with elements of char

but the signature leaves only the stream type 'a t unspecified,
providing no way for the element type to vary in the implementation.

One solution is to change the StreamOps signature to include both the
element type and the stream type.  Once you've added an element type
to the signature there's no need to parameterize the stream type:

   module type StreamOps = sig
     type elt (* the element type *)
     type t   (* the stream type *)
     val head : t -> elt
   end

The implementations of StreamOps then become functors over the element
type.  This is the approach used in the standard library to define
maps and sets (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Set.Make.html).
 For example, you might define LazyStream as follows

   module LazyStream (E : sig type elt end)
      : StreamOps with type elt = E.elt =
   struct
     type elt = E.elt
     type t = Cons of elt * t Lazy.t
     let head (Cons (h, _)) = h
   end

The element type of StmStr doesn't vary, so there's no need to make it
a functor:

   module StmStr : StreamOps with type elt = char =
   struct
     type elt = char
     type cursor = { ofs: int; lim: int; data: string }
     type t = int * cursor
     let get s i = String.get s.data i
     let head (i, s) = get s i
   end

I hope that helps,

Jeremy.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] Unifying buildt-in types with polymorphic types
  2014-05-15 20:28 ` Jeremy Yallop
@ 2014-05-16 21:41   ` Peter Frey
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Frey @ 2014-05-16 21:41 UTC (permalink / raw)
  To: Jeremy Yallop; +Cc: Caml List

On Thu, 2014-05-15 at 21:28 +0100, Jeremy Yallop wrote:
> On 15 May 2014 20:24, Peter Frey <pjfrey@sympatico.ca> wrote:
> > I need all streams to have the same signature 'StreamOps'.
> 
> It's not possible with the current definition of StreamOps.  The
> difficulty is that the stream type and the element type vary
> non-uniformly in your various stream implementations:
> 
>    StmLzy defines streams of type 'a t = Cons of 'a * 'a t Lazy.t
>                   with elements of 'a
> 
>    StmAry defines streams of type 'a t = int * 'a cursor
>                   with elements of 'a
> 
>    StmStr defines streams of type 'a t = int * 'a cursor
>                   with elements of char
> 
> but the signature leaves only the stream type 'a t unspecified,
> providing no way for the element type to vary in the implementation.
> 
> One solution is to change the StreamOps signature to include both the
> element type and the stream type.  Once you've added an element type
> to the signature there's no need to parameterize the stream type:
> 
>    module type StreamOps = sig
>      type elt (* the element type *)
>      type t   (* the stream type *)
>      val head : t -> elt
>    end
> 
> The implementations of StreamOps then become functors over the element
> type.  This is the approach used in the standard library to define
> maps and sets (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Set.Make.html).
>  For example, you might define LazyStream as follows
> 
>    module LazyStream (E : sig type elt end)
>       : StreamOps with type elt = E.elt =
>    struct
>      type elt = E.elt
>      type t = Cons of elt * t Lazy.t
>      let head (Cons (h, _)) = h
>    end
> 
> The element type of StmStr doesn't vary, so there's no need to make it
> a functor:
> 
>    module StmStr : StreamOps with type elt = char =
>    struct
>      type elt = char
>      type cursor = { ofs: int; lim: int; data: string }
>      type t = int * cursor
>      let get s i = String.get s.data i
>      let head (i, s) = get s i
>    end
> 
> I hope that helps,
> 
> Jeremy.
> 
This helped a lot, thank you.  
(Typing is hard; I have been programming since 1963 and always had a
clear idea what I was doing, because previous languages translated
statements into code; Assemblers (many) Cobol Fortran Snobol Prolog
Pascal Cs ... Now the type checker translates types into types...
perhaps I am getting to old...)
thanks again
Peter



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-05-16 21:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-15 19:24 [Caml-list] Unifying buildt-in types with polymorphic types Peter Frey
2014-05-15 20:28 ` Jeremy Yallop
2014-05-16 21:41   ` Peter Frey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).