Loading ...
Sorry, an error occurred while loading the content.

Re: "ocaml_beginners"::[] changing names => from in_channel to unit ?!

Expand Messages
  • Manos Renieris
    ... ^^^^^^^^^ read_line has type: unit - string (it doesn t need a channel, it reads from standard input). The function you need is input_line . The compiler
    Message 1 of 6 , Mar 13, 2003
    • 0 Attachment
      On Fri, Mar 14, 2003 at 12:33:24AM +0100, oliver@...-berlin.de wrote:
      > Hello,
      >
      > Well there are two basic functions, which read in the
      > file and create the output data.
      > One is called input_header, the other is called
      > input_body.
      > The problem now is, that they are of input-type unit,
      > instead of input-type in_channel.
      >
      > So instead of in_channel -> string list * string list
      > they have unit -> string list * string list
      >
      > Now here comes the Code:
      >
      >
      > #################################################################
      > (* Here we have functions to read the mail-header,
      > the mail-body, and both together *)
      >
      > let fl = Stack.create()
      >
      >
      > let input_header chan =
      > let rec read_lines_helper res =
      > let sl =
      > try
      > Some (Stack.pop fl)
      > with _ -> begin
      > try
      > Some (read_line chan)
      ^^^^^^^^^

      read_line has type: unit -> string
      (it doesn't need a channel, it reads from standard input).
      The function you need is "input_line".

      The compiler knows the type of read_line (unit->string)
      from which it infers that chan must be of type unit.

      -- Manos
    • Stalkern 2
      Il Friday 14 March 2003 00:33, oliver@first.in-berlin.de ha scritto: [...] ... Look: # read_line;; - : unit - string = : while you probably want to use
      Message 2 of 6 , Mar 13, 2003
      • 0 Attachment
        Il Friday 14 March 2003 00:33, oliver@...-berlin.de ha scritto:

        [...]

        > let fl = Stack.create()
        >
        >
        > let input_header chan =
        > let rec read_lines_helper res =
        > let sl =
        > try
        > Some (Stack.pop fl)
        > with _ -> begin
        > try
        > Some (read_line chan)
        > with
        > End_of_file -> None (* no new headers *)
        > end
        > in
        > match sl with
        > None -> List.rev res
        > | Some line when String.length line = 0 -> List.rev res (* Header
        > complete *) | Some l -> read_lines_helper (l :: res) (* prepend new line
        > *) in
        > read_lines_helper []
        >

        Look:

        # read_line;;
        - : unit -> string = <fun>:

        while you probably want to use

        # input;;
        - : in_channel -> string -> int -> int -> int = <fun>

        with some buffer string as for copying files.

        If you look at code, generally you see where types are inferred. Here you were
        afraid of a mistyping for "chan", and "chan" appears in the function body
        "read_line chan", so the first check was about the typing implied by the
        read_line function.

        Ciao
        Ernesto
      • oliver@first.in-berlin.de
        ... Wow! Thanks again. The functions first had the names input_header and input_body. Then I renamed them via global search-and-replace to read_header and
        Message 3 of 6 , Mar 13, 2003
        • 0 Attachment
          On Thu, Mar 13, 2003 at 06:46:03PM -0500, Manos Renieris wrote:
          > On Fri, Mar 14, 2003 at 12:33:24AM +0100, oliver@...-berlin.de wrote:
          > > Hello,
          > >
          > > Well there are two basic functions, which read in the
          > > file and create the output data.
          > > One is called input_header, the other is called
          > > input_body.
          > > The problem now is, that they are of input-type unit,
          > > instead of input-type in_channel.
          > >
          > > So instead of in_channel -> string list * string list
          > > they have unit -> string list * string list
          > >
          > > Now here comes the Code:
          > >
          > >
          > > #################################################################
          > > (* Here we have functions to read the mail-header,
          > > the mail-body, and both together *)
          > >
          > > let fl = Stack.create()
          > >
          > >
          > > let input_header chan =
          > > let rec read_lines_helper res =
          > > let sl =
          > > try
          > > Some (Stack.pop fl)
          > > with _ -> begin
          > > try
          > > Some (read_line chan)
          > ^^^^^^^^^
          >
          > read_line has type: unit -> string
          > (it doesn't need a channel, it reads from standard input).
          > The function you need is "input_line".
          >
          > The compiler knows the type of read_line (unit->string)
          > from which it infers that chan must be of type unit.

          Wow!

          Thanks again.

          The functions first had the names input_header and input_body.
          Then I renamed them via global search-and-replace to
          read_header and read_body.
          After the problems I renamed them back by hand, hoping that
          an error will show me the problem...

          ...there was a typing-error/warning, but it didn't show
          me the problem.

          So, thanks.
          I now know, which functions I had renaed too!

          Ciao,
          Oliver
        • oliver@first.in-berlin.de
          ... So I have to look where a function is used the first time in the code? So, when an error occurs, I look for that function and then look for it s first
          Message 4 of 6 , Mar 13, 2003
          • 0 Attachment
            On Fri, Mar 14, 2003 at 01:00:46AM +0100, Stalkern 2 wrote:
            > Il Friday 14 March 2003 00:33, oliver@...-berlin.de ha scritto:
            >
            > [...]
            >
            > > let fl = Stack.create()
            > >
            > >
            > > let input_header chan =
            > > let rec read_lines_helper res =
            > > let sl =
            > > try
            > > Some (Stack.pop fl)
            > > with _ -> begin
            > > try
            > > Some (read_line chan)
            > > with
            > > End_of_file -> None (* no new headers *)
            > > end
            > > in
            > > match sl with
            > > None -> List.rev res
            > > | Some line when String.length line = 0 -> List.rev res (* Header
            > > complete *) | Some l -> read_lines_helper (l :: res) (* prepend new line
            > > *) in
            > > read_lines_helper []
            > >
            >
            > Look:
            >
            > # read_line;;
            > - : unit -> string = <fun>:
            >
            > while you probably want to use
            >
            > # input;;
            > - : in_channel -> string -> int -> int -> int = <fun>
            >
            > with some buffer string as for copying files.
            >
            > If you look at code, generally you see where types are inferred. Here you were
            > afraid of a mistyping for "chan", and "chan" appears in the function body
            > "read_line chan", so the first check was about the typing implied by the
            > read_line function.

            So I have to look where a function is used the first time
            in the code?

            So, when an error occurs, I look for that function
            and then look for it's first occurence?

            Did I understand correctly?

            Ciao,
            Oliver
          • Stalkern 2
            ... No, you have to look where an identifier is casted to a specific type by the type inference mechanism. Type specification (and wrong type specification) if
            Message 5 of 6 , Mar 13, 2003
            • 0 Attachment
              Il Friday 14 March 2003 02:36, oliver@...-berlin.de ha scritto:
              > So I have to look where a function is used the first time
              > in the code?
              >
              > So, when an error occurs, I look for that function
              > and then look for it's first occurence?
              >
              > Did I understand correctly?
              >
              > Ciao,
              > Oliver


              No, you have to look where an identifier is casted to a specific type by the
              type inference mechanism.

              Type specification (and wrong type specification) if any are made
              either by you, with type casting
              # let aFun (aArg:string) = aArg;;
              val aFun : string -> string = <fun>

              or by the type checking mechanism
              # let aFun aArg = aArg;;
              val aFun : 'a -> 'a = <fun>
              # let aNewFun aArg1 =
              let aArg2 = aFun aArg1 in
              print_endline aArg2 (*polymorphism of aArg2 is over*) ;;
              val aNewFun : string -> unit = <fun>

              In your code example, I did not look where "function was used for the first
              time" but "where the polymorphic argument was loosing its polymorphism" (at
              the very beginning, everything is polymorphic: that's maybe why CAML stands
              for *Categorical* Abstract ML).

              A semi-automatic way to detect the same point was to impose your desired type
              by a cast and then let the compiler detect the incoherence . This was
              possible because you knew that chan had to have type in_channel .
              =========================================
              # let fl = Stack.create();;
              val fl : '_a Stack.t = <abstr>

              #let input_header (chan:in_channel) (*type casting here*)=
              let rec read_lines_helper res =
              let sl =
              try
              Some (Stack.pop fl)
              with _ -> begin
              try
              Some (read_line chan)
              with
              End_of_file -> None (* no new headers *)
              end
              in
              match sl with
              None -> List.rev res
              | Some line when String.length line = 0 -> List.rev res (* Header
              complete *)
              | Some l -> read_lines_helper (l :: res) (* prepend new line *)
              in
              read_lines_helper [];;
              val fl : '_a Stack.t = <abstr>
              # Characters 212-216:
              Some (read_line chan)
              ^^^^
              This expression has type in_channel but is here used with type unit
              =========================================
              So you can have Ocaml telling you the weird passage.

              Ernesto
            Your message has been successfully submitted and would be delivered to recipients shortly.