I'm trying to write a function "dom_rank r1 r2" that returns a boolean depending on the relative ranks of two playing Cards (rank is a type I defined, it has values "Six", "Seven", "Eight" ..... "King", "Ace"). If r1 is a King and r2 is a Jack, r1 is greater than r2 and the function returns true, and if r1 is Six and r2 is Ten then the function returns false. I understand that I could list out every possibility of two card inputs (I'm only dealing with cards Six-Ace, that makes about 30 different possibilities) but I'm trying to write simpler code. The method looks something like:
let dom_rank r1 r2 = match r1, r2 with
| Ace, _ -> true
| King, (Queen || Jack || Ten ........) -> true
I'm getting a syntax error at the beginning of the boolean expression "(Queen || Jack || Ten ........)". Why can't I list several possibilities for r2 in this way? Is there a way to write this expression in Ocaml?
The "||" operator is a boolean operator, you must separate patterns with a simple "|", like this:
| King, (Queen | Jack | Ten | ... ) -> true
However, with this method, you'll still end up writing the word "Six" a lot of time.
A good approach would be to use wildcards cleverly like that:
match r1, r2 with
| Ace, _ -> true
| _, Ace -> false (* at this point, neither card is an ace *)
| King, _ -> true
| _, King -> false
| Queen, _ -> true
| (* and so on *)
This way you only have two patterns per card rank, and no cardname as to be typed more than twice (and the non-cardname stuff can be copy-pasted)
A not so safe but convenient approach is to check that your type definition is in the right order:
type rank = Six | Seven | Eight | ... | Ace
let () = assert ( Six < Eight )
With this definition, the cards should be in the good order with respect to the standard comparison operators (see module Pervasives). Make sure to put some tests though, because any modification to the type may break your order.
As you said yourself, || is a boolean operator. Queen, Jack etc. are not boolean values. Therefore you can not apply boolean operators to them (not to mention that you can't use arbitrary expressions as patterns in a match).
What you can do is to put multiple patterns next to each separated by | like this:
| King, Queen | King, Jack| King, Ten |... -> true
Of course that's not as succinct as you need to spell out King each time. You can avoid them by using nested pattern matches rather than matching on a tuple:
let dom_rank r1 r2 =
match r1 with
| Ace -> true
| King->
(match r2 with
| Ace -> false
| _ -> true)
| ...
| Seven ->
(match r2 with
| Six, Five, Four, Three, Two -> true
| _ -> false)
Another approach would be to define a function that maps each rank to an integer and then just define dom_rank as:
let dom_rank r1 r2 = int_of_rank r1 >= int_of_rank r2
That should cut down on a lot of repetition and is the best version in my opinion.
Related
If i have a snippet similar to this one:
Inductive Q : Set :=
| NULL : Q
| CELL : nat -> Q -> Q -> Q
.
Definition someFunc (q: Q) :=
match q with
| NULL => True
| CELL 0 -> q1 -> q2 => True
| CELL z -> q1 -> q2 => (someFunc q1) || (someFunc q2)
end.
Will the case where q is 0 -> Q -> Q -> Q exhaust the match and finish the function execution, or will it drop down the next branch and destructure 0 as z?
The title of you question is not representative of the mistakes you made in your original question. You think you have a problem with exhaustive pattern-matching (you don't), while you have a mere problem of syntax and basic typing.
You managed to define an type of trees (called Q) with two constructors. That part is good.
You attempted to define a function, which by the look of it, is a recursive function. When defining a recursive function, you should use the keyword Fixpoint.
When writing a pattern in a pattern match construct, you have to respect the syntax for function application. So what you wrote Cell 0 -> q1 -> q2 should probably be written Cell 0 q1 q2.
The values returned in different branches of the pattern-match construct are in different type: True has type Prop, while an expression of the form (someFunc q1) || (someFunc q2) has type bool. These are two different types. There are two different notions of or connectives for these two types. One is written || the other one (which you should have used) is written \/.
So here is an example of code that is similar to yours, but does not suffer with syntax or typing problems.
Inductive Q : Set :=
| NULL : Q
| CELL : nat -> Q -> Q -> Q
.
Fixpoint someFunc (q: Q) :=
match q with
| NULL => True
| CELL 0 q1 q2 => True
| CELL z q1 q2 => (someFunc q1) \/ (someFunc q2)
end.
Maybe reading a few more examples of existing Coq code would help you get a better feeling of the syntax. The supplementary material of the Coq'Art book provides a few of these examples (in particular, you can look at the material for chapter 1 and chapter 6).
| (true, Select(true)) => true
| (false, Select(false)) => false
How can I combine these two in a switch statement with generic type?
Unfortunately the patterns that you match against in a switch statement have to be 'linear' (ie, the variants inside the patterns should only appear once):
See https://caml.inria.fr/pub/docs/oreilly-book/html/book-ora016.html
A pattern must necessarily be linear, that is, no given variable can occur more than once inside the pattern being matched. Thus, we might have hoped to be able to write:
# let equal c = match c with
(x,x) -> true
| (x,y) -> false;; Characters 35-36: This variable is bound several times in this matching
But this would have required the compiler to know how to carry out
equality tests. Yet this immediately raises numerous problems. If we
accept physical equality between values, we get a system which is too
weak, incapable of recognizing the equality between two occurrences of
the list [1; 2], for example. If we decide to use structural equality,
we run the risk of having to traverse, ad infinitum, circular
structures.
Note that ReasonML is just an alternative syntax for OCaml, so the above also holds for Reason. match is just the OCaml version of switch.
It is possible to combine the two cases generically using a when guard:
let f = (a, b) =>
switch (a, b) {
| (a, Select(b)) when a == b => a
};
However, note that this isn't exhaustive, and you haven't specified what should be returned in the case that a != b. To avoid the non-exhaustiveness warning, and crash at runtime, you need to add another case to cover that.
Yeah this is doable:
// using switch
let theSolution = x => switch(x) {
| (_, Select(inside)) => inside
};
// using `fun`
let theSolution = x => x |> fun | (_, Select(inside)) => inside;
// or for a super short solution:
let theSolution = fun | (_, Select(inside)) => inside;
For example:
type select = | Select(bool);
let a = (true, Select(true));
let b = (true, Select(false));
let c = (false, Select(true));
let d = (false, Select(false));
let theSolution = x => x |> fun | (_, Select(inside)) => inside;
Js.log2("A is", theSolution(a));
Js.log2("B is", theSolution(b));
Js.log2("C is", theSolution(c));
Js.log2("D is", theSolution(d));
Will result in:
"A is" true
"B is" false
"C is" true
"D is" false
Or if you want to compare the booleans, you can do either of:
let theSolution = fun | (a, Select(b)) => a && b;
let theSolution = fun | (a, Select(b)) => a == b;
See this example in the online repl
Following can be a solution for your problem. The operation a&&b depends on what logic you want the block to follow. I took a reasonable assumption that you wanted to perform AND operation. If you provide other possible conditions then this can be refined.
let getSelectionResponse = x => switch(x){ | (a, Select(b)) => a&&b};
Tried it here
I noticed something today. Scala has the usual OR ||, but also the |.
My first thought was that the | was a strict OR. So true | true, will evaluate to false.
But,
val x = true
x: Boolean = true
val y = true
y: Boolean = true
x || y
res4: Boolean = true
x | y
res5: Boolean = true
What is the | operator for? Is it just an alias?
As in Java, the single & and | operators do the same thing as their usual versions but without short-circuiting.
As an example, consider the expression true || isNice(). The method will never be called because true || x is always true and the compiler (and runtime) knows that. If you insist on all parts of a boolean expression to be evaluated, you have to use & or |.
Edit: For completeness, Scala also uses the | for alternative patterns in pattern matching. This is copied from the language reference:
8.1.11 Pattern Alternatives
Syntax:
Pattern ::= Pattern1 { ‘|’ Pattern1 }
A pattern alternative p1 | ... | pn consists of a number of alternative patterns
pi
. All alternative patterns are type checked with the expected type of the pattern.
They may no bind variables other than wildcards. The alternative pattern matches
a value v if at least one its alternatives matches v.
In at least some of the ML family languages, you can define records on which you can perform pattern matching e.g. http://learnyouahaskell.com/making-our-own-types-and-typeclasses - the basic idea is that you define a record type with named fields, a constructor is automatically created with those fields as parameters so you can create records of that type, and an extractor is automatically created with those fields as parameters so you can pattern match on records of that type.
Scala goes a step further and allows the fields stored in the record, the constructor parameters and the extractor parameters to be decoupled from each other e.g. http://daily-scala.blogspot.com/2009/11/overloaded-unapply.html - in this it is living up to its goal of supporting both object-oriented and functional programming. (Object-oriented languages of course normally allow stored fields and constructor parameters to be decoupled, though they don't normally have extractors.)
Are there any other languages that have pattern matching and allow such decoupling?
Has anything been written about the pros and cons of such decoupling?
I admit that I don't have 100% of the background required to understand your question, but I can say that F# has a feature called "Active Patterns" that it seems could be used to build the same functionality that your daily-scala link demonstrates.
Is that in the neighborhood of what you're looking for?
No, F# also provides that feature.
Examples in the second article can be implemented using Partial Active Patterns:
let (|String|_|) = function "s" -> Some "yay" | _ -> None
let (|Int|_|) = function 1 -> Some "hmm" | _ -> None
let (|StringList|_|) = function "x" -> Some [1; 2; 3] | _ -> None
let (|IntList|_|) = function 1 -> Some ["one"; "two"] | _ -> None
match 1 with
| Int s -> printfn "%O" s
| _ -> printfn "Unmatched"
match "s" with
| String s -> printfn "%O" s
| _ -> printfn "Unmatched"
match "x" with
| StringList [x; y; z] -> printfn "%O" (x, y, z)
| _ -> printfn "Unmatched"
match 1 with
| IntList [x; y] -> printfn "%O" (x, y)
| _ -> printfn "Unmatched"
Active Patterns is a powerful technique, you can even write it in a recursive way. Its combination with pattern matching provides a convenient toolkit for destructuring data. However, pattern matching is inexhaustive so you have to use wildcard(_) as the last pattern.
For reference, Don Syme (the inventor of F#) wrote a paper about F#'s "Active Patterns": Extensible Pattern Matching Via a Lightweight Language Extension – Syme, et al.
There is a long history of first class patterns in typed functional languages.
In Haskell land, we use the -XViewPatterns extension for programmatic patterns.
The first true view patterns go back to Phil Wadler's 1987 paper on views
I want to implement an arbitrary signature in SML. How can I define a datatype for terms over that signature ?I would be needing it to write functions that checks whether the terms are well formed .
In my point of view, there are two major ways of representing an AST. Either as series of (possibly mutually recursive) datatypes or just as one big datatype. There are pros an cos for both.
If we define the following BNF (extracted from the SML definition and slightly simplified)
<exp> ::= <exp> andalso <exp>
| <exp> orelse <exp>
| raise <exp>
| <appexp>
<appexp> ::= <atexp> | <appexp> <atexp>
<atexp> ::= ( <exp>, ..., <exp> )
| [ <exp>, ..., <exp> ]
| ( <exp> ; ... ; <exp> )
| ( <exp> )
| ()
As stated this is simplified and much of the atexp is left out.
1. A series of possibly mutually recursive datatypes
Here you would for example create a datatype for expressions, declarations, patterns, etc.
Basicly you would create a datatype for each of the non-terminals in your BNF.
We would most likely create the following datatypes
datatype exp = Andalso of exp * exp
| Orelse of exp * exp
| Raise of exp
| App of exp * atexp
| Atexp of atexp
and atexp = Tuple of exp list
| List of exp list
| Seq of exp list
| Par of exp
| Unit
Notice that the non-terminal has been consumed into exp datatype instead of having it as its own. That would just clutter up the AST for no reason. You have to remember that a BNF is often written in such a way that it also defined precedens and assosiativity (e.g., for arithmetic). In such cases you can often simplify the BNF by merging multiple non-terminals into one datatype.
The good thing about defining multiple datatypes is that you kind of get some well formednes of your AST. If for example we also had non-terminal for declarations, we know that the AST will newer contain a declaration inside a list (as only expressions can be there). Because of this, most of you well formedness check is not nessesary.
This is however not always a good thing. Often you need to do some checking on the AST anyways, for example type checking. In many cases the BNF is quite large and thus the number of datatypes nessesary to model the AST is also quite large. Keeping this in mind, you have to create one function for each of your datatypes,for every type of modification you wan't to do on your AST. In many cases you only wan't to change a small part of your AST but you will (most likely) still need to define a function for each datatype. Most of these functions will basicly be the identity and then only in a few cases you will do the desired work.
If for example we wan't to count how many units there are in a given AST we could define the following functions
fun countUnitexp (Andalso (e1, e2)) = countUnitexp e1 + countUnitexp e2
| countUnitexp (Orelse (e1, e2)) = countUnitexp e1 + countUnitexp e2
| countUnitexp (Raise e1) = countUnitexp e1
| countUnitexp (App (e1, atexp)) = countUnitexp e1 + countUnitatexp atexp
| countUnitexp (Atexp atexp) = countUnitatexp atexp
and countUnitatexp (Tuple exps) = sumUnit exps
| countUnitatexp (List exps) = sumUnit exps
| countUnitatexp (Seq exps) = sumUnit exps
| countUnitatexp (Par exp) = countUnitexp exp
| countUnitatexp Unit = 1
and sumUnit exps = foldl (fn (exp,b) => b + countUnitexp exp) 0 exps
As you may see we are doing a lot of work, just for this simple task. Imagine a bigger grammar and a more complicated task.
2. One (big) datatype (nodes) -- and a Tree of these nodes
Lets combine the datatypes from before, but change them such that they don't (themself) contain their children. Because in this approach we build a tree structure that has a node and some children of that node. Obviously if you have an identifier, then the identifier needs to contain the actual string representation (e.g., variable name).
So lets start out by defined the nodes for the tree structure.
(* The comment is the kind of children and possibly specific number of children
that the BNF defines to be valid *)
datatype node = Exp_Andalso (* [exp, exp] *)
| Exp_Orelse (* [exp, exp] *)
| Exp_Raise (* [exp] *)
| Exp_App (* [exp, atexp] *)
(* Superflous:| Exp_Atexp (* [atexp] *) *)
| Atexp_Tuple (* exp list *)
| Atexp_List (* exp list *)
| Atexp_Seq (* exp list *)
| Atexp_Par (* [exp] *)
| Atexp_Unit (* [] *)
See how the Atexp from the tupe now becomes superflous and thus we remove it. Personally I think it is nice to have the comment next by telling which children (in the tree structure) we can expect.
(* Note this is a non empty tree. That is you have to pack it in an option type
if you wan't to represent an empty tree *)
datatype 'a tree = T of 'a * 'a tree list
(* Define the ast as trees of our node datatype *)
type ast = node tree
We then define a generic tree and define the type ast to be a "tree of nodes".
If you use some library then there is a big chance that such a tree structure is already present. Also it might be handy late on to extend this tree structure to contain more than just the node as data, however we just keep it simple here.
fun foldTree f b (T (n, [])) = f (n, b)
| foldTree f b (T (n, ts)) = foldl (fn (t, b') => foldTree f b' t)
(f (n, b)) ts
For this example we define a fold function over the tree, again if you are using a library then all these functions for folding, mapping, etc. are most likely already defined.
fun countUnit (Atexp_Unit) = 1
| countUnit _ = 0
If we then take the example from before, that we wan't to count the number of occurances of unit, we can then just fold the above function over the tree.
val someAST = T(Atexp_Tuple, [ T (Atexp_Unit, [])
, T (Exp_Raise, [])
, T (Atexp_Unit, [])
]
)
A simple AST could look like the above (note that this is actually not valid as we have a Exp_Raise with no children). And we could then do the counting by
foldTree (fn (a,b) => (countUnit a) + b) 0 someAST
The down side of this approach is that you have to write a check function that verifies that your AST is well formed, as there is no restrictions when you create the AST. This includes that the children are of the correct "type" (e.g., only Exp_* as children in an Exp_Andalso) and that there are the correct number of children (e.g., exactly two children in Exp_Andalso).
This approach also requires a bit of builk getting started, given you don't use some library that has a tree defined (including auxilary functions for modifying the tree). However in the long run it pays of.