Standard ML - Going through a tutorial but example fails - sml

I'm going through the tutorial here...
http://www.soc.napier.ac.uk/course-notes/sml/tut2.htm
where it defines several things to be used as a function...
val first = hd o explode;
val second = hd o tl o explode;
val third = hd o tl o tl o explode;
val fourth = hd o tl o tl o tl o explode;
val last = hd o rev o explode;
Which then is used...
fun roll s = fourth s ^ first s ^ second s ^ third s;
It seems like it should work but when I try that, I get the following errors below. Anyone know what might be going?
stdIn:159.14-159.53 Error: operator and operand don't agree [tycon mismatch]
operator domain: string * string
operand: char * char
in expression:
fourth s ^ first s
stdIn:159.14-159.53 Error: operator and operand don't agree [tycon mismatch]
operator domain: string * string
operand: _ * char
in expression:
fourth s ^ first s ^ second s
stdIn:159.14-159.53 Error: operator and operand don't agree [tycon mismatch]
operator domain: string * string
operand: _ * char
in expression:
fourth s ^ first s ^ second s ^ third s

The concatenation operator concatenates strings (it's type is string * string -> string), but the first, second, ... functions are of type string -> char. Obviously we're going to get a complaint from the compiler if we try to give ^ a char * char tuple.
The tutorial links to this page with a fix:
Change the definitions given in question 6 to
fun roll s = implode[fourth s,first s,second s,third s];
fun exch s = implode[second s,first s,third s,fourth s];
I'd imagine their code works in some version of SML, but it doesn't work in SML/NJ for me, despite the fact their note is only for Moscow ML.

The error is saying that the operator ^ works on strings like this:
"ab" ^ "cd" == "abcd"
However, the functions first, second, third, fourth and last all return chars.
The function implode from the string standard library would help here.

Related

How to extract information from a record in OCaml

I have a type record:
type record = { first : string; second : string list; third : string }
I want to extract data from it using match...How would I do that?..
Please let me know. Thanks!
You can match the whole record:
match my_record with
| { first = "something"; } -> do_something
| { second = hd :: tl; third = "something else"; } -> do_something_else
(* ... *)
or target specific fields in it with the dot notation:
match my_record.second with
| hd :: tl -> do_something
(* ... *)
It is also possible to destructure a record in a function with a syntactic shortcut called field punning:
let fun_example { first; third; _ } =
"This is first: " ^ first ^ " and this is third: " ^ third
or by providing aliases for the fields:
let fun_example_2 { first = f; third = t; _ } =
"This is first: " ^ f ^ " and this is third: " ^ t
The underscore ; _ in the pattern is used to tell the compiler it shouldn't worry about incomplete matches when the #warnings "+9" directive is turned on in the toplevel. It may be omitted depending on your style.
For more intricate details please refer to RWO, there's a great chapter on records!

Could anyone explain this OCAML syntax to me

I am trying to append a string to an existing string.
I came across this thread here which explains it.
Just for reference I am pasting the content here from that page
let (^$) c s = s ^ Char.escaped c (* append *)
let ($^) c s = Char.escaped c ^ s (* prepend *)
Now I wanted to know what does (^$) mean in
let (^$) c s = s ^ Char.escaped c (* append *)
This page here states that
operator ^ is for string concatenation
what is (^$) ?
#icktoofay is correct, this code:
let (^$) c s = s ^ Char.escaped c
is defining a new operator ^$.
You can use an operator as an ordinary (prefix) function name by enclosing it in parentheses. And, indeed, this is what you do when you define an operator.
$ ocaml
OCaml version 4.02.1
# (+) 44 22;;
- : int = 66
# let (++++) x y = x * 100 + y;;
val ( ++++ ) : int -> int -> int = <fun>
# 3 ++++ 5;;
- : int = 305
Infix operators in OCaml start with one of the operator-like characters =<>#^|&+-*/$%, then can have any number of further operator-like characters !$%&*+-./:<=>?#^|~. So you can have an infix operator $^ or $^??#+ and so on.
See Section 6.1 of the OCaml manual.
It is to append the given character to the string with escaping:
'x' ^$ "hello" ----> "hellox"
'\n' ^$ "hello" ----> "hello\\n"

OCaml string and Coq string (Extraction from Coq to OCaml)

I used the extraction from Coq to OCaml, where I have type Z, N, positive
I don't use to extract it in int of OCaml.
Then the type I have after the extraction is:
type positive =
| Coq_xI of positive
| Coq_xO of positive
| Coq_xH
type coq_N =
| N0
| Npos of positive
type coq_Z =
| Z0
| Zpos of positive
| Zneg of positive
I have a program in OCaml where some functions using the OCaml type string.
In my OCaml program, I need to write some functions convert the type: string -> coq_N, string -> coq_Z, string -> positive
I tried to write the functions in Coq and then used the extraction to get the OCaml type but Coq string is different from OCaml string.
For instance:
open Ascii
open BinNums
open Datatypes
type string =
| EmptyString
| String of ascii * string
let string_of_coqN (s: string): coq_N =
match s with
| EmptyString -> N0
| String (a, _) -> (coq_N_of_ascii a);;
where coq_N_of_ascii is the extraction from coq function N_of_ascii.
When I applied the function string_of_coqN, for instance:
let test (x: string) = string_of_N x;;
I got the complain that
Error: This expression has type string but an expression was expected of type
String0.string
Could you please help me to find a way to write the convert functions : string -> coq_N, string -> coq_Z and string -> positive?
For strings, the easiest thing to do is probably to import the standard library module ExtrOcamlString in your extraction file, which will cause Coq to extract them as a char list in OCaml. You can then convert between char list and native strings with custom code. Have a look for instance at file lib/Camlcoq.v in the CompCert distribution, functions camlstring_of_coqstring and coqstring_of_camlstring.

Pattern matching from a [String] in Haskell

I'm following an introductory course on functional programming, where we use Haskell.
Part of an excercise is to write a parser for the input string.
However I can't solve the following error, or get what is actually happening.
Parser.hs:29:71:
Couldn't match expected type `String' with actual type `Char'
In the first argument of `readPoint', namely `start'
In the expression: readPoint start
In the expression:
(readLines track, readPoint start, readLine finish)
The error originates from this line:
readTrack str = parseTrack (lines str) where
parseTrack (start : finish : track) = (readLines track, readPoint start, readLine finish)
What I expected to happen is that the input string got split into a list of lines, which get passed to parseTrack.
parseTrack would then use pattern matching to name the top two strings(lines) from the list and the rest.
However what I believe is happening is that finish is the top element from the list, and start gets assigned the top char from that string.
I would really like to know how to solve this problem and what is actually happening.
Thanks a lot!
Parser.hs
module Parser where
import Types
readFloat :: String -> Float
readFloat str = case reads str of
[] -> error "not a floating point number"
(p,_):_ -> p
readInt :: String -> Int
readInt str = case reads str of
[] -> error "not an integer"
(p,_):_ -> p
readPoint :: String -> Point
readPoint str = parsePoint (words str) where
parsePoint (x : y : _) = (readInt x, readInt y)
readLine :: String -> Line
readLine str = parseLine (words str) where
parseLine (x1 : y1 : x2 : y2 : _) = ((readInt x1, readInt y1), (readInt x2, readInt y2))
readLines :: String -> [Line]
readLines str = parseLines (lines str) where
parseLines (line : rest) = readLine line : parseLines rest
readTrack :: String -> Track
readTrack str = parseTrack (lines str) where
parseTrack (start : finish : track) = (readLines track, readPoint start, readLine finish)
Types.hs
module Types where
type Vector2D = (Int, Int)
type Point = Vector2D
type Line = (Point, Point)
type Velocity = Vector2D
type CarState = (Position, Velocity)
type Position = Vector2D
type Trace = [Position]
type Track = ([Line], Point, Line)
Your variable track was actually a list of single lines, not a string with '\n's in it. Since you've already split it into lines, you can just map readLine over it, giving:
readTrack str = parseTrack (lines str) where
parseTrack (start:finish:tracks)
= (map readLine tracks, readPoint start, readLine finish)
Here tracks :: [String], which is why you can map readLine on them all - you don't need to use readLines to split it into lines first. (You can tell it's a list because it's the final thing to the right hand side of a :.)
You say
However what I believe is happening is that finish is the top element from the list, and start gets assigned the top char from that string.
Well what was happening was: because you asked for readLines track as the first output, Haskell started there, and since you declared
readLines :: String -> [Line]
that meant that track had to be a String - that's the only thing readLines can deal with.
First, you need to remember that : has an element on its left and a list on its right, so in
3:4:stuff
stuff has to be [Integer] because it's on the right of some Integer elements. Similarly,
c:"a string"
means c has to be a Char because String = [Char].
In your code, we've worked out that track is a String, so that means that when you write
(start : finish : track)
both start and finish have to be elements you can put at the front of a String, so both start and finish have to be Char.
Haskell then looks at your code readPoint start, but because it's worked out that start has type Char, but
readPoint :: String -> Point
it complains that Char and String don't match.
I think you made the mistake because you forgot that readLines takes a single string, but it felt (from the name) like it should happily take a list of strings. Your parseLines looks like it does a similar thing, but it takes a list of strings, so copes, whereas readLines takes a single string with newline characters, so can't cope with a list.
UPD. Oh, sorry, I didn't get that track means multiple tracks and has to be of type [String]. So the answer from AndrewC fits more.
Since in haskell the pattern (x:xs) means that if x has type a then xs has to be of type [a] your pattern in parseTrack means in types smth like (a : a : [a]).
Compiler wanna evaluate type a and first what it see on the right is readLines track. Func readLines has type String -> [Line] so compiler has track as String which means [a] is of type String. Also in haskell String is [Char] so a is Char.
But you need a as String. So you just need to take first three strings and throw out the rest tail of [String]. In types it'll mean smth like (String : String : String : [String]). For it you can rewrite matching pattern in parseTrack to:
parseTrack (start : finish : track : _)

Type errors when using same name

I have 3 files:
1) cpf0.ml
type string = char list
type url = string
type var = string
type name = string
type symbol =
| Symbol_name of name
2) problem.ml:
type symbol =
| Ident of string
3) test.ml
open Problem;;
open Cpf0;;
let symbol b = function
| Symbol_name n -> Ident n
When I combine test.ml: ocamlc -c test.ml.
I received an error:
This expression has type Cpf0.name = char list
but an expression was expected of type string
Could you please help me to correct it? Thank you very much
EDIT: Thank you for your answer. I want to explain more about these 3 files:
Because I am working with extraction in Coq to Ocaml type: cpf0.ml is generated from
cpf.v :
Require Import String.
Definition string := string.
Definition name := string.
Inductive symbol :=
| Symbol_name : name -> symbol.
The code extraction.v:
Set Extraction Optimize.
Extraction Language Ocaml.
Require ExtrOcamlBasic ExtrOcamlString.
Extraction Blacklist cpf list.
where ExtrOcamlString
I opened: open Cpf0;; in problem.ml, and I got a new problem because in problem.ml they have another definition for type string
This expression has type Cpf0.string = char list
but an expression was expected of type Util.StrSet.elt = string
Here is a definition in util.ml defined type string:
module Str = struct type t = string end;;
module StrOrd = Ord.Make (Str);;
module StrSet = Set.Make (StrOrd);;
module StrMap = Map.Make (StrOrd);;
let set_add_chk x s =
if StrSet.mem x s then failwith (x ^ " already declared")
else StrSet.add x s;;
I was trying to change t = string to t = char list, but if I do that I have to change a lot of function it depend on (for example: set_add_chk above). Could you please give me a good idea? how I would do in this case.
EDIT 2: I am sorry to edit this question many times. After follow the answer, I fixed the file problem.ml
type symbol =
| Ident of Cpf0.string
In problem.ml they have another definition like this. And the type one again does not accepted.
module SymbSet = Set.Make (SymbOrd);;
let rec ident_of_symbol = function
| Ident s -> s
let idents_of_symbols s =
SymbSet.fold (fun f s -> StrSet.add (ident_of_symbol f) s) s StrSet.empty;;
This expression has type Cpf0.string = char list but an expression was expected of type Util.StrSet.elt = string
You need to open module Cpf0 in problem.ml because the type string in modules Cfp0 and Problem is not the same.
problem.ml:
open Cpf0
type symbol =
| Ident of string
or better, don't open the module and prefix the type string like this:
type symbol =
| Ident of Cpf0.string