Pattern Matching SML? - functional-programming

Can someone please explain the: "description of g"? How can f1 takes unit and returns an int & the rest i'm confused about too!!
(* Description of g:
* g takes f1: unit -> int, f2: string -> int and p: pattern, and returns
* an int. f1 and f2 are used to specify what number to be returned for
* each Wildcard and Variable in p respectively. The return value is the
* sum of all those numbers for all the patterns wrapped in p.
*)
datatype pattern = Wildcard
| Variable of string
| UnitP
| ConstP of int
| TupleP of pattern list
| ConstructorP of string * pattern
datatype valu = Const of int
| Unit
| Tuple of valu list
| Constructor of string * valu
fun g f1 f2 p =
let
val r = g f1 f2
in
case p of
Wildcard => f1 ()
| Variable x => f2 x
| TupleP ps => List.foldl (fn (p,i) => (r p) + i) 0 ps
| ConstructorP (_,p) => r p
| _ => 0
end
Wildcard matches everything and produces the empty list of bindings.
Variable s matches any value v and produces the one-element list holding (s,v).
UnitP matches only Unit and produces the empty list of bindings.
ConstP 17 matches only Const 17 and produces the empty list of bindings (and similarly for other integers).
TupleP ps matches a value of the form Tuple vs if ps and vs have the same length and for all i, the i-th element of ps matches the i-th element of vs. The list of bindings produced is all the lists from the nested pattern matches appended together.
ConstructorP(s1,p) matches Constructor(s2,v) if s1 and s2 are the same string (you can compare them with =) and p matches v. The list of bindings produced is the list from the nested pattern match. We call the strings s1 and s2 the constructor name.
Nothing else matches.

Can someone please explain the: "description of g"? How can f1 takes unit and returns an int & the rest i'm confused about too!!
The function g has type (unit → int) → (string → int) → pattern → int, so it takes three (curried) parameters of which two are functions and one is a pattern.
The parameters f1 and f2 must either be deterministic functions that always return the same constant, or functions with side-effects that can return an arbitrary integer / string, respectively, determined by external sources.
Since the comment speaks of "what number to be returned for each Wildcard and Variable", it sounds more likely that the f1 should return different numbers at different times (and I'm not sure what number refers to in the case of f2!). One definition might be this:
local
val counter = ref 0
in
fun uniqueInt () = !counter before counter := !counter + 1
fun uniqueString () = "s" ^ Int.toString (uniqueInt ())
end
Although this is just a guess. This definition only works up to Int.maxInt.
The comment describes g's return value as
[...] the sum of all those numbers for all the patterns wrapped in p.
Since the numbers are not ascribed any meaning, it doesn't seem like g serves any practical purpose but to compare the output of an arbitrarily given set of f1 and f2 against an arbitrary test that isn't given.
Catch-all patterns are often bad:
...
| _ => 0
Nothing else matches.
The reason is that if you extend pattern with additional types of patterns, the compiler will not notify you of a missing pattern in the function g; the catch-all will erroneously imply meaning for cases that are possibly yet undefined.

Related

SML Create function receives list of tuples and return list with sum each pair

I'm studying Standard ML and one of the exercices I have to do is to write a function called opPairs that receives a list of tuples of type int, and returns a list with the sum of each pair.
Example:
input: opPairs [(1, 2), (3, 4)]
output: val it = [3, 7]
These were my attempts, which are not compiling:
ATTEMPT 1
type T0 = int * int;
fun opPairs ((h:TO)::t) = let val aux =(#1 h + #2 h) in
aux::(opPairs(t))
end;
The error message is:
Error: unbound type constructor: TO
Error: operator and operand don't agree [type mismatch]
operator domain: {1:'Y; 'Z}
operand: [E]
in expression:
(fn {1=1,...} => 1) h
ATTEMPT 2
fun opPairs2 l = map (fn x => #1 x + #2 x ) l;
The error message is: Error: unresolved flex record (need to know the names of ALL the fields
in this context)
type: {1:[+ ty], 2:[+ ty]; 'Z}
The first attempt has a typo: type T0 is defined, where 0 is zero, but then type TO is referenced in the pattern, where O is the letter O. This gets rid of the "operand and operator do not agree" error, but there is a further problem. The pattern ((h:T0)::t) does not match an empty list, so there is a "match nonexhaustive" warning with the corrected type identifier. This manifests as an exception when the function is used, because the code needs to match an empty list when it reaches the end of the input.
The second attempt needs to use a type for the tuples. This is because the tuple accessor #n needs to know the type of the tuple it accesses. To fix this problem, provide the type of the tuple argument to the anonymous function:
fun opPairs2 l = map (fn x:T0 => #1 x + #2 x) l;
But, really it is bad practice to use #1, #2, etc. to access tuple fields; use pattern matching instead. Here is a cleaner approach, more like the first attempt, but taking full advantage of pattern matching:
fun opPairs nil = nil
| opPairs ((a, b)::cs) = (a + b)::(opPairs cs);
Here, opPairs returns an empty list when the input is an empty list, otherwise pattern matching provides the field values a and b to be added and consed recursively onto the output. When the last tuple is reached, cs is the empty list, and opPairs cs is then also the empty list: the individual tuple sums are then consed onto this empty list to create the output list.
To extend on exnihilo's answer, once you have achieved familiarity with the type of solution that uses explicit recursion and pattern matching (opPairs ((a, b)::cs) = ...), you can begin to generalise the solution using list combinators:
val opPairs = map op+

Higher order function on lists Ocaml

I created a function p that checks if the square of a given value is lower than 30.
Then this function is called in an other function (as argument) to return the first value inside a list with its square less then 30 ( if p is true, basically I have to check if the function p is true or false ).
This is the code :
let p numb =
let return = (numb * numb) < 30 in return
let find p listT =
let rec support p listT =
match listT with
| []-> raise (Failure "No element in list for p")
| hd :: tl -> if p hd then hd
else support p tl in
let ret = support (p listT) in ret
let () =
let a = [5;6;7] in
let b = find p a in print_int b
But it said on the last line :
Error: This expression (p) has type int -> bool
but an expression was expected of type int -> 'a -> bool
Type bool is not compatible with type 'a -> bool
However, I don't think I'm using higher order functions in the right way, I think it should be more automatic I guess, or not?
First, note that
let return = x in return
can replaced by
x
Second, your original error is on line 10
support (p listT)
This line makes the typechecker deduce that the p argument of find is a function that takes one argument (here listT) and return another function of type int -> bool.
Here's another way to look at your problem, which is as #octachron says.
If you assume that p is a function of type int -> bool, then this recursive call:
support (p listT)
is passing a boolean as the first parameter of support. That doesn't make a lot of sense since the first parameter of support is supposed to be a function.
Another problem with this same expression is that it requires that listT be a value of type int (since this is what p expects as a parameter). But listT is a list of ints, not an int.
A third problem with this expression is that it only passes one parameter to support. But support is expecting two parameters.
Luckily the fix for all these problems is exremely simple.

How can I do pattern matching on tuple constructors (OCaml)

I have the following types:
type letter = A | B | C | D (*...*)
type mix = Char of letter | Mix of (mix * int) list
I want to make a function, which counts the number of occuriencies of a letter in a mix, but struggling to do the pattern matching right.
let rec count_char letter mix = match mix with
| Char l -> (*...*)
| Mix (m, i) -> (*...*)
I am getting this error
Error: This pattern matches values of type 'a * 'b
but a pattern was expected which matches values of type
(mix * int) list
It's not that it's a tuple, it's that it is a list of tuples that you're trying to match against a single tuple. Mix ((m, i) :: _) will work, but will of course result in a partial match unless you also have a branch that matches the empty list.

Recursive function to repeat string in OCaml

I am absolute OCaml beginner. I want to create a function that repeats characters 20 times.
This is the function, but it does not work because of an error.
let string20 s =
let n = 20 in
s ^ string20 s (n - 1);;
string20 "u";;
I want to run like this
# string20 "u"
- : string = "uuuuuuuuuuuuuuuuuuuu"
Your function string20 takes one parameter but you are calling it recursively with 2 parameters.
The basic ideas are in there, but not quite in the right form. One way to proceed is to separate out the 2-parameter function as a separate "helper" function. As #PierreG points out, you'll need to delcare the helper function as a recursive function.
let rec string n s =
if n = 0 then "" else s ^ string (n - 1) s
let string20 = string 20
It is a common pattern to separate a function into a "fixed" part and inductive part. In this case, a nested helper function is needed to do the real recursive work in a new scope while we want to fix an input string s as a constant so we can use to append to s2. s2 is an accumulator that build up the train of strings over time while c is an inductor counting down to 1 toward the base case.
let repeat s n =
let rec helper s1 n1 =
if n1 = 0 then s1 else helper (s1 ^ s) (n1 - 1)
in helper "" n
A non-tail call versions is more straightforward since you won't need a helper function at all:
let rec repeat s n =
if n = 0 then "" else s ^ repeat s (n - 1)
On the side note, one very fun thing about a functional language with first-class functions like Ocaml is currying (or partial application). In this case you can create a function named repeat that takes two arguments n of type int and s of type string as above and partially apply it to either n or s like this:
# (* top-level *)
# let repeat_foo = repeat "foo";;
# repeat_foo 5;;
- : bytes = "foofoofoofoofoo" (* top-level output *)
if the n argument was labeled as below:
let rec repeat ?(n = 0) s =
if n = 0 then "" else s ^ repeat s (n - 1)
The order of application can be exploited, making the function more flexible:
# (* top-level *)
# let repeat_10 = repeat ~n:10;;
# repeat_10 "foo";;
- : bytes = "foofoofoofoofoofoofoofoofoofoo" (* top-level output *)
See my post Currying Exercise in JavaScript (though it is in JavaScript but pretty simple to follow) and this lambda calculus primer.
Recursive functions in Ocaml are defined with let rec
As pointed out in the comments you've defined your function to take one parameter but you're trying to recursively call with two.
You probably want something like this:
let rec stringn s n =
match n with
1 -> s
| _ -> s ^ stringn s (n - 1)
;;

Default recursion on recursive types

Idiomatic F# can nicely represent the classic recursive expression data structure:
type Expression =
| Number of int
| Add of Expression * Expression
| Multiply of Expression * Expression
| Variable of string
together with recursive functions thereon:
let rec simplify_add (exp: Expression): Expression =
match exp with
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
| _ -> exp
... oops, that doesn't work as written; simplify_add needs to recur into subexpressions. In this toy example that's easy enough to do, only a couple of extra lines of code, but in a real program there would be dozens of expression types; one would prefer to avoid adding dozens of lines of boilerplate to every function that operates on expressions.
Is there any way to express 'by default, recur on subexpressions'? Something like:
let rec simplify_add (exp: Expression): Expression =
match exp with
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
| _ -> recur simplify_add exp
where recur might perhaps be some sort of higher-order function that uses reflection to look up the type definition or somesuch?
Unfortunately, F# does not give you any recursive function for processing your data type "for free". You could probably generate one using reflection - this would be valid if you have a lot of recursive types, but it might not be worth it in normal situations.
There are various patterns that you can use to hide the repetition though. One that I find particularly nice is based on the ExprShape module from standard F# libraries. The idea is to define an active pattern that gives you a view of your type as either leaf (with no nested sub-expressions) or node (with a list of sub-expressions):
type ShapeInfo = Shape of Expression
// View expression as a node or leaf. The 'Shape' just stores
// the original expression to keep its original structure
let (|Leaf|Node|) e =
match e with
| Number n -> Leaf(Shape e)
| Add(e1, e2) -> Node(Shape e, [e1; e2])
| Multiply(e1, e2) -> Node(Shape e, [e1; e2])
| Variable s -> Leaf(Shape e)
// Reconstruct an expression from shape, using new list
// of sub-expressions in the node case.
let FromLeaf(Shape e) = e
let FromNode(Shape e, args) =
match e, args with
| Add(_, _), [e1; e2] -> Add(e1, e2)
| Multiply(_, _), [e1; e2] -> Multiply(e1, e2)
| _ -> failwith "Wrong format"
This is some boilerplate code that you'd have to write. But the nice thing is that we can now write the recursive simplifyAdd function using just your special cases and two additional patterns for leaf and node:
let rec simplifyAdd exp =
match exp with
// Special cases for this particular function
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
// This now captures all other recursive/leaf cases
| Node (n, exps) -> FromNode(n, List.map simplifyAdd exps)
| Leaf _ -> exp

Resources