I'm a Haskell beginner,
I have a function
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
Each recursion I want to append the value to a list for my output. This function will sum consecutive indexes in a list so that the input [1, 2, 3, 4] produces [1, 3, 6, 10].
How do I append the value generated each time to my list?
Your problem here isn't how to append, but rather how to calculate the value in the first place. Each item needs to be substituted with a sum of itself with all the items preceding it.
Here is one way to do it:
Prelude> func (x:xs) = x:map (+ x) (func xs); func [] = []
Prelude> func [1, 2, 3, 4]
[1,3,6,10]
How does this work? We're given a list that starts with the element x and has the remaining elements xs. We want to increment every item in xs by x, after recursively applying the algorithm to xs.
This is what x:map (+ x) (func xs) does. It reads as "prepend x to the result of mapping every element in func xs through an increment by x".
E.g. for [1, 2, 3, 4], we want 1 to be added to every member of the result of recursively applying the algorithm to [2, 3, 4], then prepended. For [2, 3, 4] we want 2 to be ... to [3, 4]. And so on, until eventually for [4] we want 4 to be added and prepended to the result of applying the algorithm to [].
This is where our base case (func [] = []) kicks in: the algorithm is defined so that it returns an empty list unchanged. Hence func [4] is [4], func [3, 4] is [3, 7], and you keep incrementing and prepending until you get [1,3,6,10].
I think in this particular case, you could use scanl1 like:
scanl1 (+) [1,2,3,4] -- [1,3,6,10]
When iterating over lists, we often use folds, which is a way of reducing the list to a particular value.
There's also another type of operation, which is a fold that collects all results along the way, and that's called a scan (from the docs):
scanl = scanlGo
where
scanlGo :: (b -> a -> b) -> b -> [a] -> [b]
scanlGo f q ls = q : (case ls of
[] -> []
x:xs -> scanlGo f (f q x) xs)
So the scan takes three arguments: a function that takes two values and returns a value, a starter value, and a list of values.
The scan will then return a list.
Thus, what you need is a function that takes two values and returns something of the same type as the first (it's okay if both are the same). Binary addition would work here: +.
You also need a value to start off with (the b, which is the second argument to our function), and 0 is the identity for integer addition, so we should use that.
Finally, we pass your list to get the result.
Try to figure out how to write you function as a fold and then as a scan and you will discover the answer.
Related
fun map f nil = nil
| map f (hd::tl) = f(hd) :: map f tl;
fun everywhere e nil = [[e]]
| everywhere e (y::ys) =
(e::y::ys) :: (map (fn u => y::ys) (everywhere e ys));
I don't know how those sml codes work.
I know map function.
But about everywhere code, I don't know how much I think about that.
Please let me know
Thank you
First, I guess "everywhere" should be fixed to get the behavior expected from its name:
fun everywhere e nil = [[e]]
| everywhere e (y::ys) =
(e::y::ys) :: (map (fn u => y::u) (everywhere e ys));
This modified version provides a list of list. For example,
- everywhere 4 [1,2,3] ;
val it = [[4,1,2,3],[1,4,2,3],[1,2,4,3],[1,2,3,4]] : int list list
So, You may know that "everywhere e xs" enumerates all possible lists which are made by inserting item "e" into somewhere of the original list xs.
Then, how can you enumerate the insertion? It is divided into two cases:
insert at the top: [1,2,3] -> [4, 1,2,3]
insert between the first and the second or later: [1, 4 ,2,3], [1,2, 4 ,3],...
Case 1 is realized by just (e::y::ys).
Case 2 is further split into two steps:
A) get all possibilities of insertion of "e" to the sub list "ys" of the second and the following items: [4, 2, 3], [2, 4, 3], ...
B) add the first item "y" of the original list into EACH of the outcome of step A:
1 :: [4,2,3], 1::[2,4,3], ...
Step 2A can be done by calling "everywhere" itself with the sub list as an argument. Then, appending item "y" into each of (everywhere e ys), you have done Step 2B.
For this (doing the same thing for items), you can use "map".
Lets say I have nested lsit: [1, [2, 3, 4], [5, [6]]] and I want to count how many elements it has. In this case it is six elements. I have written such code for doing this:
totalElems :: [a] -> Int
totalElems (x:xs) = case (x, xs) of
(_, []) -> 0
(y:ys, _) -> 1 + totalElems ys + totalElems xs
(_, _) -> 1 + totalElems xs
But I've got an error:
a.hs:4:42:
Couldn't match expected type ‘a’ with actual type ‘[a0]’
‘a’ is a rigid type variable bound by
the type signature for totalElems :: [a] -> Int at a.hs:1:15
Relevant bindings include
xs :: [a] (bound at a.hs:2:15)
x :: a (bound at a.hs:2:13)
totalElems :: [a] -> Int (bound at a.hs:2:1)
In the pattern: y : ys
In the pattern: (y : ys, _)
In a case alternative:
(y : ys, _) -> 1 + totalElems ys + totalElems xs
How I can do this in Haskell?
You can't make freeform lists-within-lists like that in Haskell. Dynamically typed langues will tolerate silliness like that, but strongly-typed Haskell won't.
1 is of type Int, and [2,3,4] is of a different type [Int]. Things in a list have to be of the same type.
However, you could do something like this:
data Nest a = Elem a | List [Nest a]
example ::Nest Int
example = List [Elem 1, List [Elem 2, Elem 3, Elem 4], List [Elem 5, List [Elem 6]]]
countNest :: Nest a -> Int
countNest (Elem x) = 1
countNest (List xs) = sum $ map countNest xs
Let's say I have nested lsit: [1, [2, 3, 4], [5, [6]]]
You can't have that list. It won't type-check. Try typing it by itself in GHCi; it'll just spit an error message at you. Since this input can't exist in the first place, trying to write a function to process it is a doomed endeavor.
Instead, you need to define a custom data type for this. See the other answers.
As others have said, the simplest way to do this is with a different data structure, like the tree NovaDenizen defined. However, just so you know, Haskell's type system enables various ways of creating "lists" in which the elements have different types : see https://wiki.haskell.org/Heterogenous_collections
I have [[Integer]] -> [Integer] and want to take the first element of the first sub-list, the second element of the second sub-list and .. the n-th element of the n-th sub-list and so on.
I am trying to achieve this using list comprehensions. However, I first drop an incrementing number of elements and the take the head of the remaining. But there again I don't know how to use drop (inc z) where z = 0 with inc c = c + 1 as an already defined function, in presumably this:
getNext :: [[Integer]] -> [Integer]
getNext xs = [y | drop (inc z) (y:ys) <- xs, (y:_) <- xs]
where z = 0
I know that the code above is not working, but again I had only so far come up to this and hit a wall.
You can do it like this:
getNext :: [[a]] -> [a]
getNext xs = [ head $ drop y x | (x,y) <- zip xs [0..]]
Although note that this function is partial because of head.
As the other answers suggest, you can use a zip function and zip with the list of indices.
The Glasgow Haskell Compiler (GHC) however offers the Parallel List Comp extension:
{-# LANGUAGE ParallelListComp #-}
diagonal :: [[a]] -> [a]
diagonal ls = [l !! i | l <- ls | i <- [0..]]
The (!!) operator gets the i-th element from a list.
Furthermore it is always advisable to use the most generic function signature; so [[a]] -> [a] instead of [[Integer]] -> [Integer]. This can be useful if you later decide to take the diagonal of a matrix of Double's, String, lists, custom types,...
You can zip the actual list of list of integers and another list which runs from 0 to infinity and get the corresponding elements, like this
picker :: [[Integer]] -> [Integer]
picker xs = [(x !! y) | (x, y) <- (zip xs [0..])]
main = print $ picker [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
-- [1,5,9]
The expression [0..] will create an infinite list, lazily, starting from 0 and we zip it with xs. So, on every iteration, the result of zip would be used like this
[1, 2, 3] !! 0
[4, 5, 6] !! 1
[7, 8, 9] !! 2
We get element at index 0, which is 1, on the first iteration and 5 and 9 on the following iterations.
All I've been able to find in the documentation that are relevant are ++ and concat.
I thought at first doing the following would give me what I wanted:
[1, 3, 4] ++ [4, 5, 6]
but as you know that just gives [1, 2, 3, 4, 5, 6].
What would I need to do to take in [1, 2, 3] and [4, 5, 6] and get out [[1, 2, 3], [4, 5, 6]]?
As mentioned in comments, a function to take two lists and combine them into a new list can be defined as:
combine :: [a] -> [a] -> [[a]]
combine xs ys = [xs,ys]
This function can't be applied multiple times to create a list of an arbitrary number of lists. Such a function would take a single list and a list of lists and it would add the single list to the list of lists, so it would have type:
push :: [a] -> [[a]] -> [[a]]
This is just (:), though:
push = (:)
As also mentioned in the comments, the value [x,y] can also be written as x : y : [].1 Since both cases can be done with (:), I would guess that what you really want to use is (:), sometimes consing onto [] and sometimes onto a non-empty list.
1 In fact, [x,y] is just syntactic sugar for x:y:[].
think about what the (++) operator does: it concatenates Lists, it does not construct them. This is how it concatenates text Strings into a new String (and not a list of Strings), since Strings are lists of Chars. to construct a new List out of Lists you use (:) like so:
[1,2,3]:[4,5,6]:[]
where youre adding each list as an element of a new list.
I am trying to write a function like this:
updateMatrix:: [[a]] -> a -> (x, y) ->[[a]]
This is supposed to take in a list of lists such as:
[ [1, 2, 3, 4],
[5, 6, 7, 8]]
and put the given element at the specified coordinates, so, given:
[ [1, 2, 3, 4],
[5, 6, 7, 8]] 9 (0, 1)
it should return
[ [1, 9, 3, 4],
[5, 6, 7, 8]]
I can't figure out how to do this without having to rebuild the whole matrix, please help!
You need to rebuild the matrix every time. So as long as you don't need high performance computing, you could use this legible implementation:
replace :: (a -> a) -> Int -> [a] -> [a]
replace f 0 (x:xs) = (f x):xs
replace f i (x:xs) = x : replace f (i-1) xs
replace f i [] = []
replace2D :: (a -> a) -> (Int, Int) -> [[a]] -> [[a]]
replace2D f (x,y) = replace (replace f y) x
Your function would be:
updateMatrix ll x c = replace2D (const x) c ll
Here's an implementation:
updateMatrix :: [[a]] -> a -> (Int, Int) -> [[a]]
updateMatrix m x (r,c) =
take r m ++
[take c (m !! r) ++ [x] ++ drop (c + 1) (m !! r)] ++
drop (r + 1) m
But maybe this "rebuilds the whole matrix" as you say? Note that
lists are not mutable in Haskell, so you can't destructively update
one entry, if that's what you would mean by not "rebuilding the whole
matrix".
Here’s a short one:
replace p f xs = [ if i == p then f x else x | (x, i) <- zip xs [0..] ]
replace2D v (x,y) = replace y (replace x (const v))
Now you can use it exactly like you wanted:
λ → let m = [[1, 2, 3, 4], [5, 6, 7, 8]]
λ → replace2D 9 (0, 1) m
[[1,2,3,4],[9,6,7,8]]
As others already said,
This approach is of course rather slow, and only makes sense if the structure is more complex than the lists are long. There’s easy documentation about the internal structure and complexity of things in Haskell out there.
Think of m as a pointer to a linked list of pointers, and you can see why it’s slower than a pure stream of bytes. There are better libs that use something closer to the latter.
Haskell’s values are immutable because there are no side-effects. Which is good for reliability. So you can’t change m. You can only build something out of m.
Haskell can simulate mutable references, with the help of monads. Like IORef. But using it for this would be rather wrong. There are many other questions here on Stack Overflow, explaining its usage, pros and cons.
Being a purely functional language, Haskell requires you to return a "brand new" matrix when you update an item, so you need to rebuild the whole matrix indeed (if you're actually interested in matrix processing, cast a look at matrix library rather than implementing your own).
Beware, lists are not a good choice for such manipulations, but if you do it for educational purposes, start with implementing a function that "replaces" an element in [a], then use it twice (function composition can help there) in order to get your updateMatrix function. Here is an answer that can help you on your way.