For example, I would like to define a function that extracts the first element of a list. For this function, I do not care about the case when the list is empty (e.g. I can make sure that every time I use the function, I will pass a non-empty list). But Isabelle would warn that
Missing patterns in function definition:
extracts [] = undefined
How can I deal with situations like this?
You have quite a few options available, for example:
fun extracts where "extracts xs = hd xs"
definition extracts where [simp]: "extracts = hd"
fun extracts where "extracts xs = (case xs of (x # _) ⇒ x)"
fun extracts where "extracts (x # _) = x" | "extracts [] = undefined"
Related
The motivating problem is: Code a lazy list whose elements are all possible combinations of 0 and 1 i.e. [0], [1], [0;0], [0;1], etc..
Working in OCaml, I've written auxiliary functions for generating the list of permutations of length n+1 given n and for converting a list into a lazy list. The problem comes from the final function in the below block of code:
type 'a seq =
| Nil
| Cons of 'a * (unit -> 'a seq)
let rec adder = function
| [] -> []
| [[]] -> [[0];[1]]
| xs::ys -> (0::xs)::(1::xs)::(adder ys)
let rec listtoseq = function
| [] -> Nil
| xs::ys -> Cons(xs, fun () -> listtoseq ys)
let rec appendq xq yq =
match xq with
| Nil -> yq
| Cons (x, xf) -> Cons (x, fun() -> appendq (xf ()) yq)
let genlist xs = appendq (listtoseq xs) (genlist (adder xs))
Calling genlist [[0];[1]] results in a stack overflow. The issue seems to be that since genlist is an infinite loop I want to delay evaluation, yet evaluation is needed for appendq to work.
If this were a problem where one element is added to the lazy list at a time I could solve it, but I think the difficulty is that each set of length n permutations must be added at a time, and thus I don't know any other solution besides using an append function.
One way to look at your problem is that appendq isn't lazy enough. You can make things work if you define a function appendqf with this type:
'a seq -> (unit -> 'a seq) -> 'a seq
In other words, the second parameter isn't a sequence. It's a function that returns a sequence.
(Note that this type, unit -> 'a seq, is what actually appears inside a Cons.)
I tried this and it works for me.
I'm trying to implement a function used to split a list into two equal-length halves (the problem assumes the list is of even length) in F#. Using the search function yielded a thread that deals with the exact same problem I'm trying to work through now:
Split list into two equal lists in F#
I'm trying to implement the solution given by the user Juliet, who provides a partial answer:
let cut l =
let rec cut = function
| xs, ([] | [_]) -> xs
| [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys)
cut (l, l)
Which returns the second half of the list. I'm trying to work out a way to return the first half, so I made some modifications:
let rec cut(xs, ys) =
let zs = []
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
x::zs
cut (xs, ys)
You can probably tell that F# is my first functional programming language, and I'm kinda confused as to how it works, exactly. Pattern-matching is a new thing for me, and I was never very good at recursion to start with.
From what I understand, the way pattern matching works is that it's basically a more versatile version of an if-then-else statement, where the code to the left of the -> is the conditional (the "if" bit), and everything to the right is the block of code to execute if the conditional check passes (the "then" bit).
What I'm not totally sure of is whether you're allowed to do things like this:
| x::xs, y1::y2::ys ->
x::zs
cut (xs, ys)
If pattern matching really does work like if statements, then it should be, since in an if statement it would look something like
if (x::xs && y1::y2::ys)
{
x::zs
cut (xs, ys)
}
Anyhow, it doesn't seem like the statement x::zs is allowed, since Visual Studio gives me a warning:
The result of this expression is implicitly ignored. Consider using "ignore" to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. let result = expr'.
I'm not sure what it means by that last part. I thought I had already declared the list as a local variable of the function in the line
let zs = []
All I'm trying to do is take the head of the list xs in each recursive iteration of the cut function and add it to another list zs, which when the base case is reached, would contain every element x passed over (in other words, the first half of the list), then return both xs (which contains the second half of the list) and the list containing the first half, but it doesn't seem like that's allowed?
Anyhow, it doesn't seem like the statement x::zs is allowed, since Visual Studio gives me a warning.
The expression x::zs is allowed, but Visual Studio is trying to tell you that it has no effect. x::zs creates a new list but then immediately discards it (it does not mutate the existing value!).
Based on the rest of the code provided, zs should contain the first half of the list, but zs will only ever contain the empty list [] because that's the only value it is assigned to. In a language like C#, you would simply mutate the list by appending to it but in F# you shouldn't do that. Since you're already using recursion, this is a sign that zs should be a parameter to your recursive function so that you can use the new value later. (I've found that some people understand recursion better if they think of it as a callback. When you recurse, it's like providing parameters to a callback function. Any values you want to accumulate during the recursion process need to be provided as parameters to your function.)
Putting this all together, I think what you want is something like this:
let rec cut(xs, ys, zs) =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
cut (xs, ys, x::zs)
Typically, you'd hide this function inside a non-recursive function which sets up your arguments correctly:
let cut(xs, ys) =
let rec impl(xs, ys, zs) =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
impl (xs, ys, x::zs)
impl(xs, ys, [])
Note: There's no need to use ,s to seperate arguments in F#. When you do this, you are actually declaring that a function has a single argument consisting of a tuple. This is not usually what you want and it prevents currying the function. All you need to use to separate arguments is whitespace:
let cut xs ys =
let rec impl xs ys zs =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
impl xs ys (x::zs)
impl xs ys []
Here's a way to do it by adding another accumulator value that builds up the slow items into a list:
let cut l =
let rec loop acc rem =
match rem with
| xs, ([] | [_]) -> List.rev acc, xs
| [], _ -> [], []
| x::xs, y::y'::ys -> loop (x::acc) (xs, ys)
loop [] (l, l)
> cut [1;2;3;4;5;6]
([1; 2; 3], [4; 5; 6])
I am trying to write a function in Isabelle for some tasks in an assignment
and I wanted to make sure that my function works correctly so I thought about
testing it in SML but I can't seem to be able to figure out how to write it. I
have never used/wrote/learned functional programming so I am having a little trouble
with it. Can someone help me or maybe if there is something in Isabelle about testing
how a function works can he point me to the correct direction?
The functions are the following and basically are removing the first occurrence of an
element in a list and removing all occurrences from a list
fun del1:: "'a ⇒ 'a list ⇒ 'a list" where
"del1 a Nil = Nil" |
"del1 a (x#xs) = (if x = a then xs else x#(del1 a xs))"
fun delall:: "'a ⇒ 'a list ⇒ 'a list" where
"delall a Nil = Nil" |
"delall a (x#xs) = (if x = a then (delall a xs) else x#(delall a xs))"
I am not quite sure whether I get your question. First, the syntax of Isabelle/HOL and SML is not very different. If you just want to get variants of your function in SML, probably the fastest way is using Isabelle's code generator
export_code del1 delall in SML
which results in something like
fun del1 A_ a [] = []
| del1 A_ a (x :: xs) = (if HOL.eq A_ x a then xs else x :: del1 A_ a xs);
fun delall A_ a [] = []
| delall A_ a (x :: xs) =
(if HOL.eq A_ x a then delall A_ a xs else x :: delall A_ a xs);
However, since this contains some Isabelle specific stuff (like a dictionary construction to get rid of type classes) maybe you prefer hand-written code:
fun del1 a [] = []
| del1 a (x::xs) = if x = a then xs else x :: (del1 a xs)
fun delall a [] = []
| delall a (x::xs) = if x = a then delall a xs else x :: delall a xs
On the other hand, if you just want to try out your functions on some inputs, you can do that inside Isabelle using value. E.g.,
value "del1 (2::nat) [1, 2 , 3]"
value "delall ''x'' [''x'', ''y'', ''z'', ''q'', ''x'']"
There is little to add to the answer by Chris, only this detail: In Isabelle2013-2 the Isabelle/jEdit Documentation panel has a few quickstart examples. This includes src/HOL/ex/ML.thy which shows a little bit of Isabelle/HOL as logical language and SML as functional language, and some connections between them.
I'm trying to find the largest value of a list using tail recursion. I can't use any auxiliary functions, though...so it must be done using recursion. I've written a function to find the max, starting from the head, but don't know how to implement it starting from the tail!
lmax [] = error "empty list"
lmax [x] = x
lmax (x::y::xs) =
if x > y then lmax (x::xs)
else lmax (y::xs)
The term "tail recursion" has nothing to do with the tail of a list, it is about the position of a function call.
You could say that a function call is in tail position, or that it is a tail call, if it's the last thing to happen in a function, i.e. no other computations depend on it.
Compare
fun foo xs = List.length xs
and
fun bar xs = 1 + List.length xs
In the first, the call to List.length is in tail position, because its result is returned immediately.
In the second, since we add 1 to the length, the call isn't a tail call.
"Tail recursion" is when a recursive function call is a tail call.
So you're in luck: your function already is tail recursive, since both conditional branches just return the value of a recursive call.
fun lmax l = let
fun lmaxh [] a = a
| lmaxh (x::xs) a = lmax xs Int.max(x,a)
in
lmaxh l 0
end
This works, assuming that the values are nonnegative integers.
Implementing tail recursion optimizes efficiency, because one doesn't have to evaluate and "pop-off" the stack after creating the recursive calls.
In general, to use tail-recursion, you must store some "memory" from prior computations to compare with in the current one, and update it for future computations, so as to immediately exit the function in the base case.
As such, your function is already tail recursive.
However, here is a tail-recursive maxList function, more in the spirit of SML :
fun maxList l =
let
fun maxListHelper l acc =
case l of
[] => acc
| x :: xs' => if x > acc
then (maxListHelper xs' x)
else (maxListHelper xs' acc)
in
case l of
[] => error "Empty List!"
| x :: xs' => maxListHelper xs' x
end
Your function is written in a very Haskell-like syntax with different cases handled on different lines without being explicitly declared as nested cases inside a function definition. This is quite alright, but is usually not done in SML.
Basically the function will take one parameter as a character, number and check whether it is inside the List or not ?
let rec (member: a -> List a -> Bool) x =
| [] -> False
| Cons y ys -> if x == y then True else member x ys
;;
I got the solution but it seems too vague.
Could anyone show me how to use Cons operator in this particular case ?
Thanks
In Ocaml, the cons operator is ::. But it is not the only problem of your piece of code.
Here your function takes only one argument (x) but you use it with two (member x ys), you wanted to do let rec member x l = match l with or let rec member x = function which is equivalent.
In OCaml you don't have to give the type of your values, but if you do, this is not the rigth syntax. OCaml types are not capitalized, type parameters start with '
and are placed before the type they parameterize, then the type of your function is 'a -> 'a list -> bool. Moreover, for a function you have to give the type of the parameters and the return type separately (let rec member (x : 'a) (l : 'a list) : bool =).
The operator for equality is = and not ==.
Even if it is correct, don't use if then else to return a boolean, logical operators || and && should be used instead.
Corrected code:
let rec member x = function
| [] -> false
| y :: ys -> x = y || member x ys