How can I have multiple case statements which do not interleave with each other.
A toy example for instance:
fun multi_cases(xs) =
case xs of
[] => 5
| x::ys => case x of
1 => 2
|_ => 3
| x::[] => case x of
1 => 5
| _ => 7
;
stdIn:59.17-64.28 Error: types of rules don't agree [overload conflict]
earlier rule(s): [int ty] -> [int ty]
this rule: [int ty] list -> [int ty]
in rule:
:: (x,nil) =>
(case x
of 1 => 5
| _ => 7)
The last two case statements are getting mixed up how can I tell SML that they are indeed two independent case statements rather than a continuation/separate branch of case x of 1 => 2 ...
The patterns above as pointed in the answer below have an issue with their generality.
This code has two distinct problems:
As the question Nested case statements in SML that John links to says, case-ofs are a little tricky syntactically because their list of case statements never "stops". That is, your code actually gets parsed as:
fun multi_cases xs =
case xs of
[] => 5
| x::ys => case x of
1 => 2
| _ => 3
| x::[] => case x of
1 => 5
| _ => 7
which is nonsensical because that third pattern should have belonged to the outer case-of and not the inner (the inner case-of deals with x as an int, and the outer with x::[] as an int list).
Since your indentation does not actively help the compiler towards the intended meaning, using parentheses to "stop" the case-ofs from intertwining, like that post says, is the fix:
fun multi_cases xs =
case xs of
[] => 5
| x::ys => (case x of
1 => 2
| _ => 3)
| x::[] => (case x of
1 => 5
| _ => 7)
Alternatively you could turn the outer case-of into a match on the function's arguments itself and blend the inner case-of together with it, since a single pattern match allows for arbitrarily deep matching:
fun fun_cases [] = 5
| fun_cases [1] = 5
| fun_cases [_] = 7
| fun_cases (1::_) = 2
| fun_cases (_::_) = 3
Your two cases overlap because x::xs is a more general pattern than x::[]. That is, it also covers the list x::[] by setting xs to []. You could fix that in one of two ways:
List the least general pattern first, e.g.
case xs of
[] => 5
| [x] => ...
| x::_ => ...
Make that x::xs general pattern into a less general one by specifying that the list should have at least two elements:
case xs of
x :: _ :: _ => ...
| [x] => ...
| [] => ...
Related
I'm trying to understand the following code to declare a function:
let string_of_int = function
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| _ -> "many"
which is the same as
let string_of_int2 x = match x with
|0 -> "zero"
|1 -> "one"
| 2-> "two"
_ -> "many
I understand The second way of declaring the function with is trying to match the input x with several possibilities that it could be. But I don't understand the first way to do it. What does function keyword do?
Also,
what does 'a'..'z' do in the following code?
let is_capital = function
| 'a'..'z' -> false
| 'A'..'Z' -> true
|_ -> failwith "Not a valid letter"
Why can't I have a function like this:
let examplefunc = function
|"string"-> Printf.printf "a string"
|3 -> Printf.print "an integer"
|true-> Printf.printf "a boolean"
|- -> Printf.printf "whatever"
The function keyword is a variant of fun that takes in account that the behavior of the function often directly depends on the value of the argument. For instance, if we start with the following definition of the factorial function:
For a positive integer n, n! is 1 if n = 0, and n * (n-1)! otherwise
then the natural translation to OCaml is
let factorial = function
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
like you said this strictly equivalent to
let factorial = fun n -> match n with
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
but when the argument of the function is immediately deconstructed in a pattern matching, it may be more readable to use function directly.
Concerning '0'..'9', those are range pattern that matches all characters (i.e '0'|'1'|'2'|'3'|'4'|..| '9' between the lower and upper bounds (included) of the range (following the ascii ordering of characters)
let is_digit = function '0'..'9' -> true | _ -> false
is_digit '0' (* returns true *);;
is_digit 'a' (* returns false *);;
What are nested patterns? I can't understand why the following has nested patterns:
exception BadTriple
fun zip3 list_triple =
case list_triple of
([],[],[]) => []
| (hd1::tl1,hd2::tl2,hd3::tl3) => (hd1,hd2,hd3)::zip3(tl1,tl2,tl3)
| _ => raise BadTriple
fun unzip3 lst =
case lst of
[] => ([],[],[])
| (a,b,c)::tl => let val (l1,l2,l3) = unzip3 tl
in
(a::l1,b::l2,c::l3)
end
Also, I can't understand what is different between nested pattern and nested case-expression can i get some example about those things?
A nested pattern is a pattern that contains other non-trivial patterns (where by "non-trivial" I mean "not a variable or wildcard pattern").
([], [], []) is a nested pattern because (p1, p2, p3) is a pattern (matching tuples) and [] is also a pattern (matching empty lists), which is here applied to the elements of the triple. Likewise (hd1::tl1, hd2::tl2, hd3::tl3) is a nested pattern because (p1, p2, p3) is a pattern and hd1::tl1, hd2::tl2 and hd3::tl3 are also patterns (matching non-empty lists).
A way to express the same thing without nested patterns would be to move the inner patterns into their own case expressions (though I wouldn't recommend it because, as you can see, it makes the code quite a bit more complicated):
case list_triple of
(x, y, z) =>
case x of
[] =>
case y of
[] =>
case z of
[] => []
| _ => raise BadTriple
| _ => raise BadTriple
| hd1 :: tl1 =>
case y of
[] => raise BadTriple
| h2 :: tl2 =>
case z of
[] => raise BadTriple
| h3 :: tl3 =>
(hd1,hd2,hd3)::zip3(tl1,tl2,tl3)
This is a nested case expression because we have a case expression that contains other case-expressions. The version with the nested patterns was not a nested case expression because there was only one case expression - not multiple inside each other.
Maybe it will help if we decompose the function into curry style,
which does not have nested patterns,
in the foo function below there is only 3 (non-nested) patterns,
fun foo [] [] [] = []
| foo (hd1::tl1) (hd2::tl2) (hd3::tl3) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
| foo _ _ _ = raise BadTriple
and zip3 (l1, l2, l3) = foo l1 l2 l3
it is easy to see each individual pattern when we use the as keyword,
to the right of each as is a pattern.
fun zip3 (l1 as [], l2 as [], l3 as []) = []
| zip3 (l1 as hd1::tl1, l2 as hd2::tl2, l3 as hd3::tl3) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
| zip3 _ = raise BadTriple
So, why do we consider this nesting?
we can add the as for the initial argument list_triple,
and see that we in fact have patterns within a pattern.
fun zip3 (list_triple as (l1 as [], l2 as [], l3 as [])) = []
| zip3 (list_triple as (l1 as hd1::tl1, l2 as hd2::tl2, l3 as hd3::tl3)) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
without as and the unused variables it will look much nicer.
fun zip3 ([], [], []) = []
| zip3 (hd1::tl1, hd2::tl2, hd3::tl3) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
| zip3 _ = raise BadTriple
what is nested patterns?
pattern in pattern is nested pattern.
I can't understand why it is nested patterns
| (hd1::tl1,hd2::tl2,hd3::tl3) => ...
pattern here: (list1, list2, list3)
nested pattern here: list1 -> hd1::tl1, list2 -> hd2::tl2, list3 -> hd3::tl3
| (a,b,c)::tl =>
pattern here: tuple::t1
nested pattern here: tuple -> (a, b, c)
Also i can't understand what is different between nested pattern and nested case-expression can i get some example about those things?
They are two different things. Nested pattern has been explained above. As for nested case-expression:
case something of (*case here*)
| pattern =>
case pattern of (*nested case here*)
| ...
the type is defined as follows:
gap :: (Eq a) => a -> a -> [a] -> Maybe Int
I have been stuck on this problem for more than an hour and have no idea how to approach the problem. I am aware that it requires the use of fold and am familiar with that topic.
Please take into consideration that either foldl or foldr must be used.
The output when called ought to look like this
gap 3 8 [1..10]
=Just 5
gap 8 3 [1..10]
=Nothing
gap 'h' 'l' "hello"
=Just 2
gap 'h' 'z' "hello"
=Nothing
You might dropWhile the list until you find the starting element and then fold from the right, starting with Nothing, replacing that with Just 1 once you hit the end element, and fmaping +1 to the accumulator. In code:
gap :: Eq a => a -> a -> [a] -> Maybe Int
gap from to xs = case dropWhile (/= from) xs of
[] -> Nothing
(_:rest) -> gap' to rest
gap' :: Eq a => a -> [a] -> Maybe Int
gap' to = foldr f Nothing
where f x acc | x == to = Just 1
| otherwise = (+1) <$> acc
The nice thing is that it works correctly if you have several occurences of the elements in your sequence:
*Main> gap 3 8 $ [1..10] ++ [1..10]
Just 5
*Main> gap 3 8 [1, 2, 3, 3, 3, 8]
Just 3
Maybe my solution isn't nice, but it works
import Control.Monad
import Data.Function
import Data.Foldable
(...) = (.) . (.)
gap x y = liftA2 ((guard . (> 0) =<<) ... liftA2 (subtract `on` fst))
(find ((==x) . snd)) (find((==y) . snd)) . zip [0..]
So I have this "new" two way sequence:
datatype direction = Back | Forward;
datatype 'a bseq = bNil
| bCons of 'a * (direction -> 'a bseq);
and I need a function seq2bseq : 'a seq -> 'a seq -> 'a bseq that "appends" two regular sequences into one like so:
if seqUp is 0 1 2 3 4 ... and seqDown is -1 -2 -3 -4 ... then seq2bseq will create .. -4 -3 -2 -1 0 1 2 3 4 .. . In other words the starter element is the first of seqUp(0) so if I move Back I will get to the first element of seqDown(-1) and two the second of the seqUp(1) if I move Forward.
So far I wrote the following:
fun appendq (Nil, yq) = yq
| appendq (Cons(x,xf), yq) = Cons(x,fn()=>appendq(xf(),yq));
fun seq2bseq (DownSeq) (UpSeq) =
bCons(head(UpSeq), fn (Forward) => seq2bseq appendq(head(UpSeq), DownSeq) tail(UpSeq)
| (Back) => seq2bseq tail(DownSeq) appendq(head(DownSeq), UpSeq) );
for which I get the following errors:
stdIn:28.101-28.153 Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z seq * 'Z seq -> 'Z seq
operand: 'Y seq -> 'Y seq
in expression:
seq2bseq tail
stdIn:27.5-28.155 Error: right-hand-side of clause doesn't agree with function result type [tycon mismatch]
expression: _ seq -> _ bseq
result type: _ * _ -> ('Z seq -> 'Z seq) -> _ seq -> _
in declaration:
seq2bseq = (fn arg => (fn <pat> => <exp>))
I can't figure out what's wrong(:/). Help!
Thanks!
Edit: working(?) code at: http://www.beetxt.com/mkX/.
Your type errors appear to be coming from a lack of parenthesization.
If you have functions foo and bar, and want to call foo on the result of calling bar on the value baz, then you need to write this as foo (bar baz) or foo (bar (baz)), if you prefer.
Writing foo bar(baz) will cause foo to be called with the argument bar, which will likely not type-check.
Try:
fun seq2bseq (DownSeq) (UpSeq) =
bCons(head(UpSeq),
fn Forward => seq2bseq (appendq(head(UpSeq), DownSeq)) (tail(UpSeq))
| Back => seq2bseq (tail(DownSeq)) (appendq(head(DownSeq), UpSeq))
)
I've found myself repeating a pattern over and over again, and I'd like to abstract it. I'm fairly confident that coq is sufficiently expressive to capture the pattern, but I'm having a bit of trouble figuring out how to do so. I'm defining a programming language, which has mutually recursive inductive datatypes representing the syntactic terms:
Inductive Expr : Set :=
| eLambda (x:TermVar) (e:Expr)
| eVar (x:TermVar)
| eAscribe (e:Expr) (t:IFType)
| ePlus (e1:Expr) (e2:Expr)
| ... many other forms ...
with DType : Set :=
| tArrow (x:TermVar) (t:DType) (c:Constraint) (t':DType)
| tInt
| ... many other forms ...
with Constraint : Set :=
| cEq (e1:Expr) (e2:Expr)
| ...
Now, there are a number of functions that I need to define over these types. For example, I'd like a function to find all of the free variables, a function to perform substitution, and a function to pull out the set of all constraints. These functions all have the following form:
Fixpoint doExpr (e:Expr) := match e with
(* one or two Interesting cases *)
| ...
(* lots and lots of boring cases,
** all of which just recurse on the subterms
** and then combine the results in the same way
*)
| ....
with doIFType (t:IFType) := match t with
(* same structure as above *)
with doConstraint (c:Constraint) := match c with
(* ditto *)
For example, to find free variables, I need to do something interesting in the variable cases and the cases that do binding, but for everything else I just recursively find all of the free variables of the subexpressions and then union those lists together. Similarly for the function that produces a list of all of the constraints. The substitution case is a little bit more tricky, because the result types of the three functions are different, and the constructors used to combine the subexpressions are also different:
Variable x:TermVar, v:Expr.
Fixpoint substInExpr (e:Expr) : **Expr** := match e with
(* interesting cases *)
| eLambda y e' =>
if x = y then eLambda y e' else eLambda y (substInExpr e')
| eVar y =>
if x = y then v else y
(* boring cases *)
| eAscribe e' t => **eAscribe** (substInExpr e') (substInType t)
| ePlus e1 e2 => **ePlus** (substInExpr e1) (substInExpr e2)
| ...
with substInType (t:Type) : **Type** := match t with ...
with substInConstraint (c:Constraint) : **Constraint** := ...
.
Writing these functions is tedious and error prone, because I have to write out all of the uninteresting cases for each function, and I need to make sure I recurse on all of the subterms. What I would like to write is something like the following:
Fixpoint freeVars X:syntax := match X with
| syntaxExpr eVar x => [x]
| syntaxExpr eLambda x e => remove x (freeVars e)
| syntaxType tArrow x t1 c t2 => remove x (freeVars t1)++(freeVars c)++(freeVars t2)
| _ _ args => fold (++) (map freeVars args)
end.
Variable x:TermVar, v:Expr.
Fixpoint subst X:syntax := match X with
| syntaxExpr eVar y => if y = x then v else eVar y
| syntaxExpr eLambda y e => eLambda y (if y = x then e else (subst e))
| syntaxType tArrow ...
| _ cons args => cons (map subst args)
end.
The key to this idea is the ability to generally apply a constructor to some number of arguments, and to have some kind of "map" that that preserves the type and number of arguments.
Clearly this pseudocode doesn't work, because the _ cases just aren't right. So my question is, is it possible to write code that is organized this way, or am I doomed to just manually listing out all of the boring cases?
Here's another way, though it's not everyone's cup of tea.
The idea is to move recursion out of the types and the evaluators, parameterizing it instead, and turning your expression values into folds. This offers convenience in some ways, but more effort in others -- it's really a question of where you end up spending the most time. The nice aspect is that evaluators can be easy to write, and you won't have to deal with mutually recursive definitions. However, some things that are simpler the other way can become brain-twisters in this style.
Require Import Ssreflect.ssreflect.
Require Import Ssreflect.ssrbool.
Require Import Ssreflect.eqtype.
Require Import Ssreflect.seq.
Require Import Ssreflect.ssrnat.
Inductive ExprF (d : (Type -> Type) -> Type -> Type)
(c : Type -> Type) (e : Type) : Type :=
| eLambda (x:nat) (e':e)
| eVar (x:nat)
| eAscribe (e':e) (t:d c e)
| ePlus (e1:e) (e2:e).
Inductive DTypeF (c : Type -> Type) (e : Type) : Type :=
| tArrow (x:nat) (t:e) (c':c e) (t':e)
| tInt.
Inductive ConstraintF (e : Type) : Type :=
| cEq (e1:e) (e2:e).
Definition Mu (f : Type -> Type) := forall a, (f a -> a) -> a.
Definition Constraint := Mu ConstraintF.
Definition DType := Mu (DTypeF ConstraintF).
Definition Expr := Mu (ExprF DTypeF ConstraintF).
Definition substInExpr (x:nat) (v:Expr) (e':Expr) : Expr := fun a phi =>
e' a (fun e => match e return a with
(* interesting cases *)
| eLambda y e' =>
if (x == y) then e' else phi e
| eVar y =>
if (x == y) then v _ phi else phi e
(* boring cases *)
| _ => phi e
end).
Definition varNum (x:ExprF DTypeF ConstraintF nat) : nat :=
match x with
| eLambda _ e => e
| eVar y => y
| _ => 0
end.
Compute (substInExpr 2 (fun a psi => psi (eVar _ _ _ 3))
(fun _ phi =>
phi (eLambda _ _ _ 1 (phi (eVar _ _ _ 2)))))
nat varNum.
Compute (substInExpr 1 (fun a psi => psi (eVar _ _ _ 3))
(fun _ phi =>
phi (eLambda _ _ _ 1 (phi (eVar _ _ _ 2)))))
nat varNum.
Here is a way to go, but it does not give very readable code: use tactics.
Let's say I have a language with many constructors of various arity, and I want to apply a specific goal only to the case given by constructor aaa, and I want to traverse all the other constructors, to get down to the aaa's that may appear under them. I can do the following:
Say you want to define a function A -> B (A is the type of the language), you will need to keep track of what case you are in,
so you should define a phantom type over A, reducing to B.
Definition phant (x : A) : Type := B.
I suppose that the union function has type B -> B -> B and that you have a default value in B, called empty_B
Ltac generic_process f acc :=
match goal with
|- context [phan (aaa _)] => (* assume aaa has arith 1 *)
intros val_of_aaa_component; exact process_this_value val_of_aaa_component
| |- _ =>
(* This should be used when the next argument of the current
constructor is in type A, you want to process recursively
down this argument, using the function f, and keep this result
in the accumulator. *)
let v := fresh "val_in_A" in
intros v; generic_process f (union acc (f v))
(* This clause will fail if val_in_A is not in type A *)
| |- _ => let v := fresh "val_not_in_A" in
(* This should be used when the next argument of the current
constructor is not in type A, you want to ignore it *)
intros v; generic_process f acc
| |- phant _ =>
(* this rule should be used at the end, when all
the arguments of the constructor have been used. *)
exact acc
end.
Now, you define the function by a proof. Let's say the function is called process_aaa.
Definition process_aaa (x : A) : phant x.
fix process_aaa 1.
(* This adds process_add : forall x:A, phant x. in the context. *)
intros x; case x; generic_process process_aaa empty_B.
Defined.
Note that the definition of generic_process only mention one constructor by name, aaa, all others
are treated in a systematic way. We use the type information to detect those sub-components in which we want to perform a recursive descent. If you have several mutually inductive types, you can add arguments to the generic_process function to indicate which function will be used for each type and have more clauses, one for each argument of each type.
Here is a test of this idea, where the language has 4 constructors, values to be processed are the ones that appear in the constructor var and the type nat is also used in another constructor (c2). We use the type of lists of natural numbers as the type B, with nil as the empty and singleton lists as result when encountering variables. The function collects all occurrences of var.
Require Import List.
Inductive expr : Type :=
var : nat -> expr
| c1 : expr -> expr -> expr -> expr
| c2 : expr -> nat -> expr
| c3 : expr -> expr -> expr
| c4 : expr -> expr -> expr
.
Definition phant (x : expr) : Type := list nat.
Definition union := (#List.app nat).
Ltac generic_process f acc :=
match goal with
|- context[phant (var _)] => exact (fun y => y::nil)
| |- _ => let v := fresh "val_in_expr" in
intros v; generic_process f (union acc (f v))
| |- _ => let v := fresh "val_not_in_expr" in
intros v; generic_process f acc
| |- phant _ => exact acc
end.
Definition collect_vars : forall x : expr, phant x.
fix collect_vars 1.
intros x; case x; generic_process collect_vars (#nil nat).
Defined.
Compute collect_vars (c1 (var 0) (c2 (var 4) 1)
(c3 (var 2) (var 3))).
The last computation returns a list containing values 0 4 2 and 3 as expected, but not 1, which did not occur inside a var constructor.