I seem to remember an older version of F# allowing structural decomposition when matching sequences just like lists. Is there a way to use the list syntax while keeping the sequence lazy? I'm hoping to avoid a lot of calls to Seq.head and Seq.skip 1.
I'm hoping for something like:
let decomposable (xs:seq<'a>) =
match xs with
| h :: t -> true
| _ -> false
seq{ 1..100 } |> decomposable
But this only handles lists and gives a type error when using sequences. When using List.of_seq, it seems to evaluate all the elements in the sequence, even if it is infinite.
If you use the LazyList type in the PowerPack, it has Active Patterns called LazyList.Nil and LazyList.Cons that are great for this.
The seq/IEnumerable type is not particulaly amenable to pattern matching; I'd highly recommend LazyList for this. (See also Why is using a sequence so much slower than using a list in this example.)
let s = seq { 1..100 }
let ll = LazyList.ofSeq s
match ll with
| LazyList.Nil -> printfn "empty"
| LazyList.Cons(h,t) -> printfn "head: %d" h
Seq works fine in active patterns! Unless I'm doing something horrible here...
let (|SeqEmpty|SeqCons|) (xs: 'a seq) =
if Seq.isEmpty xs then SeqEmpty
else SeqCons(Seq.head xs, Seq.skip 1 xs)
// Stupid example usage
let a = [1; 2; 3]
let f = function
| SeqEmpty -> 0
| SeqCons(x, rest) -> x
let result = f a
Remember seq has map reduce functions as well, so you might often be able to get away with only those. In the example, your function is equivalent to "Seq.isEmpty". You might try to launch fsi and just run through the tab completion options (enter "Seq." and hit tab a lot); it might have what you want.
Related
Important: I am only allowed to use List.head, List.tail and List.length
No List.map List.rev ...........etc
Only List.hd, List.tl and List.length
How to duplicate the elements of a list in a list of lists only if the length of the list is odd
Here is the code I tried:
let rec listes_paires x =
if x=[] then []
else [List.hd (List.hd x)]
# (List.tl (List.hd x))
# listes_paires (List.tl x);;
(* editor's note: I don't know where this line is supposed to go*)
if List.length mod 2 = 1 then []
For exemple:
lists_odd [[]; [1];[1;2];[1;2;3];[];[5;4;3;2;1]];;
returns
[[]; [1; 1]; [1; 2]; [1; 2; 3; 1; 2; 3]; []; [5; 4; 3; 2; 1; 5; 4; 3; 2; 1]]
Any help would be very appreciated
thank you all
It looks like that your exercise is about writing recursive functions on lists so that you can learn how to write functions like List.length, List.filter, and so on.
Start with the most simple recursive function, the one that computes the length to the list. Recall, that you can pattern match on the input list structure and make decisions on it, e.g.,
let rec length xs = match xs with
| [] -> 0 (* the empty list has size zero *)
| hd :: tl ->
(* here you can call `length` and it will return you
the length of the list hing how you can use it to
compute the length of the list that is made of `tl`
prepended with `hd` *)
???
The trick is to first write the simple cases and then write the complex cases assuming that your recursive function already works. Don't overthink it and don't try to compute how recursion will work in your head. It will make it hurt :) Just write correctly the base cases (the simple cases) and make sure that you call your function recursively and correctly combine the results while assuming that it works correctly. It is called the induction principle and it works, believe me :)
The above length function was easy as it was producing an integer as output and it was very easy to build it, e.g., you can use + to build a new integer from other integers, something that we have learned very early in our lives so it doesn't surprise us. But what if we want to build something more complex (in fact it is not more complex but just less common to us), e.g., a list data structure? Well, it is the same, we can just use :: instead of + to add things to our result.
So, lets try writing the filter function that will recurse over the input list and build a new list from the elements that satisfy the given predicate,
let rec filter xs keep = match xs with
| [] -> (* the simple case - no elements nothing to filter *)
[]
| x :: xs ->
(* we call filter and it returns the correctly filtered list *)
let filtered = filter xs keep in
(* now we need to decide what to do with `x` *)
if keep x then (* how to build a list from `x` and `filtered`?*)
else filtered (* keep filtering *)
The next trick to learn with recursive functions is how to employ helper functions that add an extra state (also called an accumulator). For example, the rev function, which reverses a list, is much better to define with an extra accumulator. Yes, we can easily define it without it,
let rec rev xs = match xs with
| [] -> []
| x :: xs -> rev xs # [x]
But this is an extremely bad idea as # operator will have to go to the end of the first list and build a completely new list on the road to add only one element. That is our rev implementation will have quadratic performance, i.e., for a list of n elements it will build n list each having n elements in it, only to drop most of them. So a more efficient implementation will employ a helper function that will have an extra parameter, an accumulator,
let rev xs =
(* we will pump elements from xs to ys *)
let rec loop xs ys = match xs with
| [] -> ys (* nothing more to pump *)
| x :: xs ->
let ys = (* push y to ys *) in
(* continue pumping *) in
loop xs []
This trick will also help you in implementing your tasks, as you need to filter by the position of the element. That means that your recursive function needs an extra state that counts the position (increments by one on each recursive step through the list elements). So you will need a helper function with an extra parameter for that counter.
I want to find all the possible partitions of a string into a list of non-empty strings.
For example if i give as input "sun",
i want to create this output : [["s","u","n"], ["s","un"], ["su","n"], ["sun"]].
I have created a simple function with recursion but it prints this overflow error i can't fix it please i need help:
partition :: String->[[String]]
partition w = [[(head w)]:fix | fix <- partition (tail w)]
++[((head w):fix):fixfix | (fix:fixfix)<-partition (tail w)]
The essential problem is that you're missing the base case for the recursion, so you have an infinite loop.
The simple thing is just to replace the head/tail mess with pattern matching, which will solve that problem as a side effect.
partition [] = [[]]
partition (w:ws) =
[[w]:fix | fix <- partition ws] ++
[(w:fix):fixfix | (fix:fixfix)<-partition ws]
This turns out to work okay, somewhat to my surprise. Why was I surprised? I figured that, with optimization, GHC would use common subexpression elimination to rewrite it to
partition [] = [[]]
partition (w:ws) =
[[w]:fix | fix <- partitionws] ++
[(w:fix):fixfix | (fix:fixfix)<-partitionws]
where partitionws = partition ws
That would be bad: it would save the entire partition ws calculation across the ++, using lots of memory. But it seems GHC is clever enough these days not to do that.
To be more confident, you can avoid the common subexpression, by accumulating a "continuation" explaining how you'll process each element you produce.
part :: ([[a]] -> [b]) -> [a] -> [b]
part f [] = f []
part f (w:ws) =
part (\fix -> f ([w]:fix)) ws ++
part (\q -> case q of
[] -> []
fix:fixfix -> f ((w:fix):fixfix)) ws
partition = part (:[])
For reasons I don't know, this version is a couple times faster than the simple one.
If you don't care about the order in which the elements are produced, you can avoid the space leak risk much more simply (and perhaps even faster) by doing something like this:
partition [] = [[]]
partition (w:ws) =
[ q
| m <- partition ws
, q <- ([w]:m) : [(w:fix):fixfix | fix:fixfix <- [m]]]
This is almost as simple as the simplest solution.
Hi I'm new to f# and I got this exercise I can't figure out:
"Implement a Function :"
let compress (l : List<'a>) : List<'a> = ...
That removes consecutive occurences of the same element in l. for example compressing [a;a;a;a;b;b;c] to [a;b;c]
I'm not allowed to use the built-in functions of f# and need to do this with pattern matching.
My current code (it's not much) :
let rec compress (l: List<'a>) : List<'a> =
match l with
| [] -> l
thanks for the help!
For any recursive function you need to consider: 1. the terminal case and 2. the general case. In your scenario:
the empty list []
non-empty list x::xs (where x represents the head of the list and xs the rest aka tail)
The other important aspect to consider when you build such a functions is to assume it works for a previous value. For example in the case of factorial, we assume the function already works for a previous scenario e.g. factorial of n-1.
let fact n =
match n with
| 0 | 1 -> 1
| _ -> n * fact (n-1)
I have to make a function that takes list a list and returns list of pairs of first and last element,2nd and 2nd last and so forth It doesn't matter if the list has even or odd number of elements because if its odd i will just ignore the middle element.The idea i have is that make a new rec fun that takes old list and its revers as input i think i finished the code but i get Syntax error for ;;
let lip l =
if [] then []
else let l1=l l2=List.rev l in
let rec lp l1 l2 = match l1,l2 with
| [],[] ->[]
| [],h2::t2->[]
| h1::_,h2::_ ->
if (List.length l -2) >= 0 then [(h1,h2)]# lp(List.tl l1) t2
else [] ;;
There are quite a few errors in your code.
I think the specific error you're seeing is caused by the fact that there is no in after let rec lp ....
Every let that's not at the top level of a module needs to be followed by in. One way to think of it is that it's a way of declaring a local variable for use in the expression that appears after in. But you need to have the in expr.
Another way to look at it is that you're defining a function named lp but you're not calling it anywhere.
As #lambda.xy.x points out, you can't say if [] then ... because [] isn't of type bool. And you can't say let x = e1 y = e2 in .... The correct form for this is let x = e1 in let y = e2 in ...
(Or you can write let x, y = e1, e2 in ..., which looks nicer for defining two similar variables to two similar values.)
The following code should at least compile:
let lip list1 =
if list1 = [] then []
else
let list2=List.rev list1 in
let rec lp l1 l2 = match l1,l2 with
| [], [] ->[]
| [], _::_->[]
| h1::_::_, h2::t2 -> (* l1 length >= 2*)
(h1,h2) :: lp(List.tl l1) t2
| h1::_,h2::t2 -> (* l1 length = 1 *)
[]
in
[]
I have made the following changes:
renamed the arguments of lip to make clear they are different from the arguments of lp
removed the alias let l1 = l
changed the if condition to a term of type boolean -- there's not much to compare, so I assume you are checking list1
replaced the list length condition by a pattern match against two heads
the else path is the second match - it might be better to rewrite that one to | [h1, _] -> ...
the definition of lp needs to be followed with the actual body of lip - to make it compile, we just return [] at the moment but you probably would like something else there
As #Jeffrey Scofield already mentioned, you are not using lp in your code. It could help if you added a comment that explains what you'd like to achieve and what the intended role of lp is.
let rec reverse l =
let s = ref [] in
match l with
| [] -> !s
| hd::tl -> s := hd :: !s
reverse tl
Maybe I'm in trouble with the last s := hd :: !s part.
How can I fix this??
One problem is that you have two expressions:
s := hd :: !s
reverse tl
You need to join these expressions into a larger expression that evaluates them in order. The way to do this is with the ; (semicolon) operator:
s := hd :: !s ;
reverse tl
Your other problem is that you have a different s in each recursive call. You need to use the same s for all the calls.
The basic layout for doing this is to have an outer function that defines s and an inner recursive function that does the work using this one s:
let outer_fun l =
let s = ref [] in
let rec inner_fun = ... in
inner_fun l
(As a side comment, it might be worth figuring out a way to do this without using a reference. Learning to write pure functions is one of the biggest benefits of learning OCaml, even if you don't go on to be a functional programmer.)