Related
I'm beginner in haskell and I tried to add a number in a 2D list with specific index in haskell but I don't know how to do
example i have this:
[[],[],[]]
and I would like to put a number (3) in the index 1 like this
[[],[3],[]]
I tried this
[array !! 1] ++ [[3]]
but it doesn't work
As you may have noticed in your foray so far, Haskell isn't like many other languages in that it is generally immutable, so trying to change a value, especially in a deeply nested structure like that, isn't the easiest thing. [array !! 1] would give you a nested list [[]] but this is not mutable, so any manipulations you do this structure won't be reflected in the original array, it'll be a separate copy.
(There are specialized environments where you can do local mutability, as with e.g. Vectors in the ST monad, but these are an exception.)
For what you're trying to do, you'll have to deconstruct the list to get it to a point where you can easily make the modification, then reconstruct the final structure from the (modified) parts.
The splitAt function looks like it will help you with this: it takes a list and separates it into two parts at the index you give it.
let array = [[],[],[]]
splitAt 1 array
will give you
([[]], [[],[]])
This helps you by getting you closer to the list you want, the middle nested list.
Let's do a destructuring bind to be able to reconstruct your final list later:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
Next, you'll need to get at the sub-list you want, which is the first item in the end list:
desired = head end
Now you can make your modification -- note, this will produce a new list, it won't modify the one that's there:
desired' = 3:desired
Now we need to put this back into the end list. Unfortunately, the end list is still the original value of [[],[]], so we'll have to replace the head of this with our desired' to make it right:
end' = desired' : (tail end)
This drops the empty sub-list at the beginning and affixes the modified list in its place.
Now all that's left is to recombine the modified end' with the original beginning:
in beginning ++ end'
making the whole snippet:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
desired = head end
desired' = 3:desired
end' = desired' : (tail end)
in beginning ++ end'
or, if you're entering all these as commands in the REPL:
let array = [[],[],[]]
let (beginning, end) = splitAt 1 array
let desired = head end
let desired' = 3:desired
let end' = desired' : (tail end)
beginning ++ end'
As paul mentions, things in Haskell are immutable. What you want to do must be done not be modifying the list in place, but by destructuring the list, transforming one of its parts, and restructuring the list with this changed part. One way of destructuring (via splitAt) is put forth there; I'd like to offer another.
Lists in Haskell are defined as follows:
data [] a = [] | a : [a]
This reads "A list of a is either empty or an a followed by a list of a". (:) is pronounced "cons" for "constructor", and with it, you can create nonempty lists.
1 : [] -> [1]
1 : [2,3] -> [1,2,3]
1 : 2 : 3 : [] -> [1,2,3]
This goes both ways, thanks to pattern matching. If you have a list [1,2,3], matching it to x : xs will bind its head 1 to the name x and its tail [2,3] to xs. As you can see, we've destructured the list into the two pieces that were initially used to create it. We can then operate on those pieces before putting the list back together:
λ> let x : xs = [1,2,3]
λ> let y = x - 5
λ> y : xs
[-4,2,3]
So in your case, we can match the initial list to x : y : z : [], compute w = y ++ [3], and construct our new list:
λ> let x : y : z : [] = [[],[],[]]
λ> let w = y ++ [3]
λ> [x,w,z]
[[],[3],[]]
But that's not very extensible, and it doesn't solve the problem you pose ("with specific index"). What if later on we want to change the thousandth item of a list? I'm not too keen on matching that many pieces. Fortunately, we know a little something about lists—index n in list xs is index n+1 in list x:xs. So we can recurse, moving one step along the list and decrementing our index each step of the way:
foo :: Int -> [[Int]] -> [[Int]]
foo 0 (x:xs) = TODO -- Index 0 is x. We have arrived; here, we concatenate with [3] before restructuring the list.
foo n (x:xs) = x : foo (n-1) xs
foo n [] = TODO -- Up to you how you would like to handle invalid indices. Consider the function error.
Implement the first of those three yourself, assuming you're operating on index zero. Make sure you understand the recursive call in the second. Then read on.
Now, this works. It's not all that useful, though—it performs a predetermined computation on a specified item in a list of one particular type. It's time to generalize. What we want is a function of the following type signature:
bar :: (a -> a) -> Int -> [a] -> [a]
where bar f n xs applies the transformation f to the value at index n in the list xs. With this, we can implement the function from before:
foo n xs = bar (++[3]) n xs
foo = bar (++[3]) -- Alternatively, with partial application
And believe it or not, changing the foo you already wrote into the much more useful bar is a very simple task. Give it a try!
I'm trying to write a method that splits a list into two. The function should return a tuple of the two lists and the arguments that the function takes are the # of items on the first list, and then the list. Here's what I mean
list [1,2,3,4]
split(1,list)-> ([1],[2,3,4])
split (3,list) -> ([1,2,3],[4])
Here's what I have so far:
let rec mysplit = function
|(n,[])->([],[])
|(1,x::xs)->(x::[],xs)
|(n,x::xs)-> mysplit(n-1,xs)
I'm not exactly sure how to "catch" the tuple back from the recursive call. Not sure where to have an extra let statement in there to temporarily save the list I'm building up. New to the language so a couple of different approaches would be good to learn.
Skip and take are your friends here. I don't think you need to do any sort of matches or recursive calls when there's a direct approach.
let split n l = (l |> Seq.take n, l |> Seq.skip n)
As for possible edge cases, skip will return an empty sequence if there are > n elements in the list, and take will return the first n elements if there are < n elements in the sequence.
Tried it in TryFharp.org with your examples and it works as expected.
A straightforward implementation would be:
let rec mysplit = function
|(n,[])->([],[])
|(1,x::xs)->(x::[],xs)
|(n,x::xs)-> let (f, s) = mysplit(n-1,xs) in (x::f, s)
You could also write a tail-recursive version:
let mysplit (n, l) =
let rec mysplit' n' (f, s) = function
| [] -> (f, s)
| (x::xs) as l' -> if n' = 0 then (f, l') else mysplit' (n'-1) (x::f, xs) xs
let (f', s) = mysplit' n ([], []) l in (List.rev f', s)
Lee's answer shows you a working solution, but to answer your specific question, you can capture values returned to you in a tuple like so:
let before, after = mysplit (2, [1;2;3;4;5])
You can also use this trick to declare multiple variables in a single let statement:
let i, j, k = (1, 2, 3)
I'm really new to F#, and I need a bit of help with an F# problem.
I need to implement a cut function that splits a list in half so that the output would be...
cut [1;2;3;4;5;6];;
val it : int list * int list = ([1; 2; 3], [4; 5; 6])
I can assume that the length of the list is even.
I'm also expected to define an auxiliary function gencut(n, xs) that cuts xs into two pieces, where n gives the size of the first piece:
gencut(2, [1;3;4;2;7;0;9]);;
val it : int list * int list = ([1; 3], [4; 2; 7; 0; 9])
I wouldn't normally ask for exercise help here, but I'm really at a loss as to where to even start. Any help, even if it's just a nudge in the right direction, would help.
Thanks!
Since your list has an even length, and you're cutting it cleanly in half, I recommend the following (psuedocode first):
Start with two pointers: slow and fast.
slow steps through the list one element at a time, fast steps two elements at a time.
slow adds each element to an accumulator variable, while fast moves foward.
When the fast pointer reaches the end of the list, the slow pointer will have only stepped half the number of elements, so its in the middle of the array.
Return the elements slow stepped over + the elements remaining. This should be two lists cut neatly in half.
The process above requires one traversal over the list and runs in O(n) time.
Since this is homework, I won't give a complete answer, but just to get you partway started, here's what it takes to cut the list cleanly in half:
let cut l =
let rec cut = function
| xs, ([] | [_]) -> xs
| [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys)
cut (l, l)
Note x::xs steps 1 element, y::y'::ys steps two.
This function returns the second half of the list. It is very easy to modify it so it returns the first half of the list as well.
You are looking for list slicing in F#. There was a great answer by #Juliet in this SO Thread: Slice like functionality from a List in F#
Basically it comes down to - this is not built in since there is no constant time index access in F# lists, but you can work around this as detailed. Her approach applied to your problem would yield a (not so efficient but working) solution:
let gencut(n, list) =
let firstList = list |> Seq.take n |> Seq.toList
let secondList = list |> Seq.skip n |> Seq.toList
(firstList, secondList)
(I didn't like my previous answer so I deleted it)
The first place to start when attacking list problems is to look at the List module which is filled with higher order functions which generalize many common problems and can give you succinct solutions. If you can't find anything suitable there, then you can look at the Seq module for solutions like #BrokenGlass demonstrated (but you can run into performance issues there). Next you'll want to consider recursion and pattern matching. There are two kinds of recursion you'll have to consider when processing lists: tail and non-tail. There are trade-offs. Tail-recursive solutions involve using an accumulator to pass state around, allowing you to place the recursive call in the tail position and avoid stack-overflows with large lists. But then you'll typically end up with a reversed list! For example,
Tail-recursive gencut solution:
let gencutTailRecursive n input =
let rec gencut cur acc = function
| hd::tl when cur < n ->
gencut (cur+1) (hd::acc) tl
| rest -> (List.rev acc), rest //need to reverse accumulator!
gencut 0 [] input
Non-tail-recursive gencut solution:
let gencutNonTailRecursive n input =
let rec gencut cur = function
| hd::tl when cur < n ->
let x, y = gencut (cur+1) tl //stackoverflow with big lists!
hd::x, y
| rest -> [], rest
gencut 0 input
Once you have your gencut solution, it's really easy to define cut:
let cut input = gencut ((List.length input)/2) input
Here's yet another way to do it using inbuilt library functions, which may or may not be easier to understand than some of the other answers. This solution also only requires one traversal across the input. My first thought after I looked at your problem was that you want something along the lines of List.partition, which splits a list into two lists based on a given predicate. However, in your case this predicate would be based on the index of the current element, which partition cannot handle, short of looking up the index for each element.
We can accomplish creating our own equivalent of this behavior using a fold or foldBack. I will use foldBack here as it means you won't have to reverse the lists afterward (see Stephens excellent answer). What we are going to do here is use the fold to provide our own index, along with the two output lists, all as the accumulator. Here is the generic function that will split your list into two lists based on n index:
let gencut n input =
//calculate the length of the list first so we can work out the index
let inputLength = input |> List.length
let results =
List.foldBack( fun elem acc->
let a,b,index = acc //decompose accumulator
if (inputLength - index) <= n then (elem::a,b,index+1)
else (a,elem::b,index+1) ) input ([],[],0)
let a,b,c = results
(a,b) //dump the index, leaving the two lists as output.
So here you see we start the foldBack with an initial accumulator value of ([],[],0). However, because we are starting at the end of the list, the 0 representing the current index needs to be subtracted from the total length of the list to get the actual index of the current element.
Then we simply check if the current index falls within the range of n. If it does, we update the accumulator by adding the current element to list a, leave list b alone, and increase the index by 1 : (elem::a,b,index+1). In all other cases, we do exactly the same but add the element to list b instead: (a,elem::b,index+1).
Now you can easily create your function that splits a list in half by creating another function over this one like so:
let cut input =
let half = (input |> List.length) / 2
input |> gencut half
I hope that can help you somewhat!
> cut data;;
val it : int list * int list = ([1; 2; 3], [4; 5; 6])
> gencut 5 data;;
val it : int list * int list = ([1; 2; 3; 4; 5], [6])
EDIT: you could avoid the index negation by supplying the length as the initial accumulator value and negating it on each cycle instead of increasing it - probably simpler that way :)
let gencut n input =
let results =
List.foldBack( fun elem acc->
let a,b,index = acc //decompose accumulator
if index <= n then (elem::a,b,index-1)
else (a,elem::b,index-1) ) input ([],[],List.length input)
let a,b,c = results
(a,b) //dump the index, leaving the two lists as output.
I have the same Homework, this was my solution. I'm just a student and new in F#
let rec gencut(n, listb) =
let rec cut n (lista : int list) (listb : int list) =
match (n , listb ) with
| 0, _ -> lista, listb
| _, [] -> lista, listb
| _, b :: listb -> cut (n - 1) (List.rev (b :: lista )) listb
cut n [] listb
let cut xs = gencut((List.length xs) / 2, xs)
Probably is not the best recursive solution, but it works. I think
You can use List.nth for random access and list comprehensions to generate a helper function:
let Sublist x y data = [ for z in x..(y - 1) -> List.nth data z ]
This will return items [x..y] from data. Using this you can easily generate gencut and cut functions (remember to check bounds on x and y) :)
check this one out:
let gencut s xs =
([for i in 0 .. s - 1 -> List.nth xs i], [for i in s .. (List.length xs) - 1 -> List.nth xs i])
the you just call
let cut xs =
gencut ((List.length xs) / 2) xs
with n durationn only one iteration split in two
I have a chained list like
["root", "foo", "bar", "blah"]
And I'd like to convert it to a list of tuples, using adjacent pairs. Like so
[("root", "foo"), ("foo", "bar"), ("bar", "blah")]
At the moment, I'm using this to do it:
zipAdj x = tail (zip ("":x) (x++[""]))
However, I don't really like this method. Can anyone think of a better way? If it's glaringly obvious I apologise, I'm fairly new to Haskell.
Okay, here's the comment as an answer:
Just zipAdj x = zip x $ tail x will suffice. zip stops upon reaching the end of the shorter of the two lists, so this simply pairs each item in the list with its successor, which seems to be all you want.
And for the sake of explaining the pointless version: zip <*> tail uses the Applicative instance for "functions from some type", which basically amounts to a lightweight inline Reader monad--in this case the list is the "environment" for the Reader. Usually this just obfuscates matters but in this case it almost makes it clearer, assuming you know to read (<*>) here as "apply both of these to a single argument, then apply the first to the second".
One possible solution:
pairs [] = []
pairs (x:[]) = []
pairs (x:y:zs) = (x, y) : pairs (y : zs)
Definitely not as small as yours, and can probably be optimized quite a bit.
It's possible to generalize the zipAdj in the question to work with arbitrary Traversable containers. Here's how we'd do it if we wanted the extra element on the front end:
import Data.Traversable
pairDown :: Traversable t => a -> t a -> t (a, a)
pairDown x = snd . mapAccumL (\old new -> (new, (old,new))) x
*Pairing> take 10 $ pairDown 0 [1..]
[(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]
*Pairing> pairDown 0 [1..10]
[(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]
To stick the extra element on the end, we can use mapAccumR:
import Data.Traversable
pairUp :: Traversable t => t a -> a -> t (a, a)
pairUp xs x = snd $ mapAccumR (\old new -> (new, (new,old))) x xs
This effectively traverses the container backwards.
*Pairing> pairUp [0..10] 11
[(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10),(10,11)]
*Pairing> take 10 $ pairUp [0..] undefined
[(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]
It's impossible to generalize the apparently-desired function in quite this fashion, but it's possible to generalize it a bit differently:
import Data.Foldable
import Prelude hiding (foldr)
pairAcross :: Foldable f => f a -> [(a,a)]
pairAcross xs = foldr go (const []) xs Nothing
where
go next r Nothing = r (Just next)
go next r (Just prev) = (prev, next) : r (Just next)
This gives
*Pairing> pairAcross [1..10]
[(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]
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.