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.
Related
I'm trying to make a function that recursively returns an element from a list of pairs. It takes two arguments, a list of pairs (an association list), and a Value, if the value matches the first element of a pair in a list, then it should return the second element of the pair. Else return an error if the value does not match. For example, searchpair([{K,V}], K). Should return V.
Here's what I've tried. Not sure how to add in the tuple and recurse on it.
searchpair([], _) -> error;
searchpair([[K, V] | Rest], Search) when V = Search -> K;
searchpair([_ | Rest], Search) -> seachPair(Rest, Search).
You don't need a when, you can bind the K directly:
searchpair([], _) ->
error;
searchpair([{K,V} | _Rest], K) ->
V;
searchpair([_T | Rest], Search) ->
searchpair(Rest, Search).
Also, a tuple is not a list. Moreover, function names are case sensitive.
I'm reading https://ocaml.org/learn/tutorials/99problems.html and it has 2 examples:
# let rec last_two = function
| [] | [_] -> None
| [x;y] -> Some (x,y)
| _::t -> last_two t;;
I understand the first one: _::t means pattern match anything and call it t
But at
# let rec at k = function
| [] -> None
| h :: t -> if k = 1 then Some h else at (k-1) t;;
I don't understand what h means. For me it should be _:: t -> ... to match anything and call it t
The pattern _ :: t doesn't mean what you say. It matches any non-empty list and calls the tail of the list t.
The pattern h :: t matches any non-empty list, calls the head of the list h (one element, the first one), and the tail of the list t (zero or more elements after the first one).
The operator :: is the list constructor (often called "cons"), which is why these patterns match lists.
Here are examples of :: as list constructor:
# true :: [];;
- : bool list = [true]
# 1 :: [2; 3];;
- : int list = [1; 2; 3]
As is usual in OCaml, the pattern for a list uses the same syntax as the constructor.
# match [1;2;3] with [] -> None | h :: t -> Some (h, t);;
- : (int * int list) option = Some (1, [2; 3])
The h::t pattern matches the head and tail of the list to the variables h and t.
So if I pattern match like this:
match [1; 2; 3] with
| h::t -> (* Some code... *)
h will have a value of 1, and t will have the value of [2; 3].
:: is a constructor. Pattern matching in this fashion pattern matches against constructors. They create a new datatype out of two values. :: is a constructor, and its type, list, is recursive. Here's a sample definition of the list type:
type 'a list =
| []
| (::) 'a * ('a list)
;;
So the list type is recursive because its constructor, ::, calls itself.
Honestly, I could write half a book on lists. They're the bread and butter of functional programming languages.
If you're wondering why you can't pattern match on operators, this is why. You can't pattern match on operators, only constructors.
Yes, indeed when you type in a function let's take for example this one:
let is_empty (l: int list) : int =
begin match l with
| [] -> 1
| h::t -> 0
end;;
Therefore, in this function that tests if a list is empty or not, if [], an empty list it returns one or in boolean true but if h::t, meaning that there is one or more value, the function returns 0, meaning it's false.
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.
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
Here is the error code I have:
Characters 2004-2008
Error: The type constructor list expects 1 argument(s),
but is here applied to 0 argument(s)
Here is the Ocaml code I have written:
let createHuffmanTree (s:string) = match s with
| "" -> Empty (*Return an empty huffman tree ifstring is empty*)
| _ -> let rec ca (l: list) (a: huffman) = match l with (*ERROR SHOULD BE ON THIS LINE*)
| [] -> a (*If list is [] return the huffman tree*)
| x,_ -> fold_left (ca) l level(leaf(x),a) (*For all the ellement of the list create a level and corresponding leaf*)
in ca listFreq(explode(s)) Empty (*Start with an empty tree*)
Note:
explode take a string return it as a list of char
ex:
# explode "Test";;
- : char list = ['T'; 'e'; 's'; 't']
listFreq take the list from explode and return a pair of char * int being the char and the number of time it is found in the list return by explode
ex:
# listeFreq (explode "AABCAABADBACAAB");;
- : (char * int) list = [('A', 8); ('B', 4); ('C', 2); ('D', 1)]
The Huffman Tree I am trying to create take a string (for exemple "AAABBC")
and do this:
level
| |
v v
leaf A level
| |
v v
leaf B leaf C
The tree could also be Empty
Question:
I have no idea how to solve the error code. Could someone point out a solution?
I suppose that instead of (l: list), you should have something like (l: 'a list).