Extracting values from a function via matching - sml

I'm working on an assignment and was given the following function:
fun label (lb,ub) =
let val s = callcc (fn k =>let fun branch c = if (c < ub)
then (pushCP (k,branch,c+1);c)
else ub
in (pushCP(k,branch,lb+1);lb)
end)
in {value=s,dom=(lb,ub)}
end;
If you put a lower and upper bound of let's say 1 and 3into this function it would print
val it = {dom=(1,3), value=1}
What I am trying to figure out is if it is at all possible to get the value. In my notes it says two possible ways of doing this would be through #value(x) or by doing val {value=a,...} = x, but I get errors both ways with this.
Any clue what I am doing wrong?

It isn't clear what you are doing wrong since you haven't reproduced what you actually tried, but your notes are correct:
- val x = {dom=(1,3), value=1};
val x = {dom=(1,3),value=1} : {dom:int * int, value:int}
The first method is to use #value to extract the value field and #dom to extract the dom field:
- #value x;
val it = 1 : int
- #dom x;
val it = (1,3) : int * int
The second method is to use pattern matching. You can extract individual fields:
- val {value = a,...} = x;
val a = 1 : int
Or you can extract both fields at once:
- val {dom = a, value = b} = x;
val a = (1,3) : int * int
val b = 1 : int
In order for the above to work, x needs to be bound to the value. Perhaps you are trying to use this with an x which hasn't been given a val binding. You would need to have something like this:
val x = label(1,3)
I don't have all the relevant code so I can't test. If the above isn't enough to answer your question, you need to provide more details.

Related

Trouble with a the explode function SML

I have a .txt file that contains this:
d3%~19^fgh54 78nm,.j
1.2k~789bv
This is the code that I have:
fun parse(L) =
let
val infile = TextIO.openIn(L)
fun read(infile) =
if TextIO.endOfStream(infile) then " " else (valOf(TextIO.inputLine(infile))) ^ read(infile);
fun split(S) = explode(S)
in
split(read(infile))
end;
This is the output I get:
[#"d",#"3",#"%",#"~",#"1",#"9",#"^",#"f",#"g",#"h",#"5",#"4",#" ",#"7",#"8",
#"n",...] : char list
I cannot figure out why the explode will not turn the whole string it is given into a char list.
The top-level printer in SML/NJ has limits for how much of data structures it prints.
You can adjust (among other things) the displayed length of lists and strings, and the depth of recursive structures with the Control.Print structure.
Example:
- Control.Print.printLength;
val it = ref 16 : int ref
- val stuff = [1,2,3,4,5,6,7,8,9,10];
val stuff = [1,2,3,4,5,6,7,8,9,10] : int list
- Control.Print.printLength := 4;
val it = () : unit
- stuff;
val it = [1,2,3,4,...] : int list
- Control.Print.printDepth;
val it = ref 5 : int ref
- val deep = [[[[[[[[]]]]]]]];
val deep = [[[[[#]]]]] : 'a list list list list list list list list
- Control.Print.printDepth := 10;
val it = () : unit
- deep;
val it = [[[[[[[[]]]]]]]] : 'a list list list list list list list list
If you want to see everything regardless of size, you need to define and use functions that print the way you like.

Using records as function arguments in SML

The one subject in SML which does not get much attention is 'records'.
I was wondering how to handle records in functions (as an argument or returented value). I know we can use the # operator in order to get an element of the record. But How should I pass the record to the function? is there a special pattern matching for that?
I have tried:
fun foo r = #1 r;
It ends with the following error:
Error: unresolved flex record
(can't tell what fields there are besides #1)
I didn't find any guide online which explains this part of records, in SML.
Also I tried:
fun foo {1=2,2=3} = 5;
And found out that tuples are actually syntax-sugar of records. Of Course I got the match warning, but at least it worked this time. The real question is how to handle 'generic' records. Could be helpful to see some examples or a reference to a guide on the subject.
It will be more then helpful to see also explanation about the signatures of those functions (as I mentioned records like {1=2,2=3} will get different signatures then {a=2,b=3}).
The one subject in SML which does not get much attention is 'records'.
I'm not sure what you mean. Standard textbooks on SML usually cover this. For example, ML for the Working Programmer, 2nd Ed. chapter 2, Names, Functions and Types, pp. 28 and on covers them. This book is free as a PDF, so you can read this chapter if you like.
If you read chapter 2, p. 34 it covers record patterns:
- val richardIII =
{ name = "Richard III"
, born = 1452
, crowned = 1483
, died = 1485
, quote = "Plots have I laid..."
};
> val richardIII =
{born = 1452, crowned = 1483, died = 1485, name = "Richard III",
quote = "Plots have I laid..."} :
{born : int, crowned : int, died : int, name : string, quote : string}
- val { name = richard_name, died = richard_died, ... } = richardIII;
> val richard_name = "Richard III" : string
val richard_died = 1485 : int
These record patterns are also possible in function arguments.
I recommend that you read a textbook on SML on this and other subjects.
StackOverflow is a poor format for reproducing one.
The real question is how to handle 'generic' records
Depending on what you mean by generic records, SML may not be able to do that.
For example, you can define the function
- fun f { x, y } = x + y;
> val f = fn : {x : int, y : int} -> int
But if you try to define one that extracts x and y from an arbitrary record without specifying the remaining record type,
- fun f { x, y, ... } = x + y;
! Toplevel input:
! fun f { x, y, ... } = x + y;
! ^^^^^^^^^^^^^
! Unresolved record pattern
Whereas if you specified the type of record,
- fun f ({ x, y, ... } : { x : int, y : int, z : int }) = x + y;
> val f = fn : {x : int, y : int, z : int} -> int
or equivalently via a type alias,
- type coord = { x : int, y : int, z : int };
> type coord = {x : int, y : int, z : int}
- fun f ({ x, y, ... } : coord) = x + y;
> val f = fn : {x : int, y : int, z : int} -> int
then that works as fine as using #x and #y:
- fun f (coord : coord) = #x coord + #y coord;
> val f = fn : {x : int, y : int, z : int} -> int
and without any kind of type annotation or inference, this will also fail to recognize the particular record type:
- fun f coord = #x coord + #y coord;
! Toplevel input:
! fun f coord = #x coord + #y coord;
! ^^
! Unresolved record pattern
So SML does not handle generic records in this sense even though it's technically possible to allow for this in a language. Perhaps this was not the meaning you went for. Perhaps record patterns were what you needed. I'll let you dig into the textbook material and resolve this.
Updated: As Andreas Rossberg suggested, I've simplified the examples a little.

Get element from a type ocaml

New to Ocaml so asking a very basic question.
If I have a type say type foobar = foo * bar and a variable a of type foobar. Is it possible to get just the value of foo from a with a method? Is there any other way than pattern matching? Also, in this case how would you apply pattern matching? Since the type declared is not declared as type foobar = | Foobar of foo * bar?
You can match against a pair like this:
# type intfloat = int * float;;
type intfloat = int * float
# let x : intfloat = (3, 5.5);;
val x : intfloat = (3, 5.5)
# let (int_part, _) = x in int_part;;
- : int = 3
# let (_, float_part) = x in float_part;;
- : float = 5.5
There is a function (not a method) fst that returns the first element of a pair.
# fst x;;
- : int = 3
However, the definition of fst necessarily uses pattern matching:
let fst (a, b) = a
In this definition, the construct (a, b) is a pattern that matches a pair.
Pattern matching is an essential part of OCaml, not just a fancy optional feature.

keeping maxInt in a variable (Standard ML)

How to put the maximum value of Integer into val in SML?
I saw that you can use intMax:
> Int.maxInt;
val it = SOME 1073741823 : int option
but If I'll try to put it as value into val, it will print error:
> val max:int = Int.maxInt;
Error: pattern and expression in val dec don't agree [tycon mismatch]
pattern: int
expression: int option
in declaration:
max : int = Int.maxInt
Although val max = Int.maxInt works, it makes:val max = SOME 1073741823 : int option.
I would like the variable to be of int type and not of int option.
In other words, the output should be:
> val max = 1073741823 : int
EDIT:
Thanks for the answer. Is it possible to put value bigger than maxInt?
I would like to calculate:
fun someCalculation num = ceil((Math.sqrt(1.0+8.0*real(num))-1.0)/2.0);
val max_int = Option.valOf Int.maxInt;
val current = someCalculation max_value;
because of 8.0*real(maxInt) it won't work. Is is possible to calculate? Notice that the final answer isn't bigger than maxInt.
How to put the maximum value of Integer into val in SML?
You can remove the "option" part using Option.valOf : 'a option -> 'a:
- val max = valOf Int.maxInt;
> val max = 1073741823 : int
Using valOf is generally not safe, since valOf NONE raises an exception:
- valOf NONE;
! Uncaught exception:
! Option
This would only happen if a future version of your compiler would ship with an arbitrary-size Int module. Since SML/NJ already has IntInf as a separate module, that's probably not going to happen right away.
Is it possible to put value bigger than maxInt?
Not using an int (too small):
- valOf Int.maxInt + 1;
! Uncaught exception:
! Overflow
And not using a real (too imprecise):
- Real.== (real (valOf Int.maxInt) + 1.0,
real (valOf Int.maxInt));
> val it = true : bool
But using the IntInf library, yes:
- IntInf.maxInt;
> val it = NONE : int option
- IntInf.fromInt (valOf Int.maxInt) * 8;
> val it = 8589934584 : IntInf.int
As you can see, SML/NJ overloads integer literals so they work both as int (read: Int31.int) and as IntInf.int.

converting a specific string into a list of a class object

If I have a case class Point(x: Double, y: Double), and val s="(12,3.5),(33,42),(19.1,3)". How to split and convert s into something like this?
Vector(Point(12,3.5),Point(33,42),Point(19.1,3))
(I was thinking first need to split s into "(12,3.5)", "(33,42)" and "(19.1,3)" but I don't know how to do this in a clean way. Afterwards, some scala regular expressions can map each element into x and y for the Point class...)
I think below code might help you.
val s = "(12,3.5),(33,42),(19.1,3)"
val p = "[0-9.]+".r
val result = p.findAllIn(s).map(_.toDouble).grouped(2).map{case Seq(x, y) => Point(x, y)}.toVector
To extract tuples from the string, consider
val xs = """(\d+(\.\d*)?\,\d+(\.\d*)?)+""".r.findAllIn(s).toArray
Array(12,3.5, 33,42, 19.1,3)
To construct the points,
for (t <- xs; Array(x,y) = t.split(","))
yield Point(x.toDouble, y.toDouble)
which delivers
Array(Point(12.0,3.5), Point(33.0,42.0), Point(19.1,3.0))