1
votes

I have been working on trying to understand this, and working any harder on it is going to hurt my relationship with OCaml, so I figured I would ask for help.

I have a simple function from this site

let line_stream_of_channel channel =
Stream.from
  (fun _ ->
     try Some (input_line channel) with End_of_file -> None);;

Okay cool, clearly from the signature below it:

val line_stream_of_channel : in_channel -> string Stream.t = <fun>

in_channel is the argument and Stream.t is the return value.

Now why is it in OCaml that I can't do:

Stream string

and instead I have to do

string Stream.t

Looking at the type signature of Stream didn't really get me anywhere either. I've noticed this same syntax weirdness with stuff like lists where you have to do the unnatural

string list

rather than the natural

list string

But what is especially weird is the ".t" portion of the Stream type above.

Can anyone kinda explain what is going on here and why things are done this way? I've googled tutorials on explicit type signatures, types, etc in OCaml and in general they lead back here to very specific questions that don't really help me.

Thank you!

2

2 Answers

1
votes

In OCaml's parameterized types, the type constructor name comes after the parameter name(s). That's just the way it works. There are languages (such as Haskell) that use the other order.

I like the OCaml order, I have no problem with it. I also have no problem with the other order.

The name t is defined as a parameterized type in the Stream module. There's nothing trickier than this going on.

However, note that the return type of line_stream_of_channel is string Stream.t, not just Stream.t. Stream.t by itself isn't a type. (It's a function at the type level, or a type constructor.)

$ ocaml
        OCaml version 4.01.0

# Some 3;;
- : int option = Some 3
# ^D

$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Prelude> :t Just (3 :: Integer)
Just (3 :: Integer) :: Maybe Integer
0
votes

Types can be parametric in OCaml. For example, int list is a list parametrized with type int, and basically corresponds to list<int> in some other languages. Is it weird? It depends on your background. I personally, find string list more natural, then list string

The syntax for parametrized type is <parameter-type> <parametrized-type>. So both components should be types. Stream is not a type, it is a module name. The notation <module-name> . <name> allows you to address definitions defined in module. For example, you may define a type alias:

 type 'a stream = 'a Stream.t

and then use it

 type string_stream = string stream

Note, stream_string sounds weird, isn't it?