I was trying to do a simulation of the Rubik's cube in Elm when I noticed Elm doesn't support list comprehensions. In Haskell or even Python I would write something like:
ghci> [2*c | c <- [1,2,3,4]]
[2,4,6,8]
I could not find a way in Elm. The actual list comprehension I had to write was (in Haskell):
ghci> let x = [0,1,3,2]
ghci> let y = [2,3,1,0]
ghci> [y !! fromIntegral c | c <- x]
[2,3,0,1]
where fromIntegral :: (Integral a, Num b) => a -> b turns Integer into Num.
In Elm, I tried to use Arrays:
x = Array.fromList [0,1,3,2]
y = Array.fromList [2,3,1,0]
Array.get (Array.get 2 x) y
And I started getting difficulties with Maybe types:
Expected Type: Maybe number
Actual Type: Int
In fact, I had to look up what they were. Instead of working around the maybe, I just did something with lists:
x = [0,1,3,2]
y = [2,3,1,0]
f n = head ( drop n x)
map f y
I have no idea if that's efficient or correct, but it worked in the cases I tried.
I guess my two main questions are:
does Elm support list comprehensions? ( I guess just use map)
how to get around the maybe types in the Array example?
is it efficient to call head ( drop n x) to get the nth element of a list?
Elm doesn't and will not support list comprehensions: https://github.com/elm-lang/Elm/issues/147
The style guide Evan refers to says 'prefer map, filter, and fold', so.. using `map:
map ((y !!).fromIntegral) x
or
map (\i-> y !! fromIntegral i) x
Commenters point out that (!!) isn't valid Elm (it is valid Haskell). We can define it as either:
(!!) a n = head (drop n a), a total function.
or perhaps
(!!) a n = case (head (drop n a)) of
Just x -> x
Nothing -> crash "(!!) index error"
I don't know much about Elm, so I can't answer to whether it supports list comprehensions (couldn't find anything via Google about it either way), but I can answer your other two questions.
How to get around the Maybe types in the Array example?
The type of Array.get is Int -> Array a -> Maybe a, which means that it returns either Nothing or Just x, where x is the value at the given index. If you want to feed the result of one of these operations into another, in Haskell you could just do
Array.get 2 x >>= \i -> Array.get i y
Or with do notation:
do
i <- Array.get 2 x
Array.get i y
However, from a quick search it seems that Elm may or may not support all monadic types, but hopefully you can still use a case statement to get around this (it's just not very fun)
case Array.get 2 x of
Nothing -> Nothing
Just i -> Array.get i y
In fact, I would recommend writing a function to do this in general for you, it's just a direct clone of >>= for Maybe in Haskell:
mayBind :: Maybe a -> (a -> Maybe b) -> Maybe b
mayBind Nothing _ = Nothing
mayBind (Just x) f = f x
Then you could use it as
Array.get 2 x `mayBind` (\i -> Array.get i y)
Is it efficient to call head (drop n x) to get the nth element of a list?
No, but neither is direct indexing, which is equivalent to head . drop n. For lists, indexing will always be O(n) complexity, meaning it takes n steps to get the nth element from the list. Arrays have a different structure, which lets them index in logarithmic time, which is significantly faster. For small lists (< 100 elements), this doesn't really matter, but once you start getting more than a hundred or a thousand elements, it starts becoming a bottleneck. Lists are great for simple code that doesn't have to be the fastest, as they are generally more convenient. Now, I don't know how exactly this gets translated in Elm, it may be that Elm will convert them into Javascript arrays, which are true arrays and indexable in O(1) time. If Elm uses its own version of Haskell lists after it's been compiled, then you'll still have a slowdown.
Related
I'm trying to grapple my head around Haskell and I'm having a hard time pinning down the general procedure/algorithm for this specific task. What I want to do is basically give Haskell a list [1,2,3,5,6,9,16,17,18,19] and have it give me back [1-3, 5, 6, 9, 16-19] so essentially turning three or more consecutive numbers into a range in the style of lowestnumber - highestnumber. What I have issue with it I suppose is the all too common difficulty grappling with with the functional paradigm of Haskell. So I would really appreciate a general algorithm or an insight into how to view this from an "Haskellian" point of view.
Thanks in advance.
If I understand the question correctly, the idea is to break up the input lists in chunks, where a chunk is either a single input element or a range of at least three consecutive elements.
So, let's start by defining a datatype for representing such chunks:
data Chunk a = Single a | Range a a
As you can see, the type is parametric in the type of input elements.
Next, we define a function chunks to actually construct a list of chunks from a list of input elements. For this, we require the ability to compare input elements and to obtain the immediate consecutive for a given input element (that is, its successor). Hence, the type of the function reads
chunks :: (Eq a, Enum a) => [a] -> [Chunk a]
Implementation is relatively straightforward:
chunks = foldr go []
where
go x (Single y : Single z : cs) | y == succ x && z == succ y = Range x z : cs
go x (Range y z : cs) | y == succ x = Range x z : cs
go x cs = Single x : cs
We traverse the list from right to left, generating chunks as we go. We generate a range if an input element precedes its two immediate consecutive elements (the first case of the helper function go) or if it precedes a range that starts with its immediate consecutive (the second case). Otherwise, we generate a single element (the final case).
To arrange for pretty output, we declare applications of the type constructor Chunk to be instances of the class Show (given that the type of input elements is in Show):
instance Show a => Show (Chunk a) where
show (Single x ) = show x
show (Range x y) = show x ++ "-" ++ show y
Returning to the example from the question, we then have:
> chunks [1,2,3,5,6,9,16,17,18,19]
[1-3,5,6,9,16-19]
Unfortunately, things are slightly more complicated if we need to account for bounded element types; such types have a largest element for which succ is undefined:
> chunks [maxBound, 1, 2, 3] :: [Chunk Int]
*** Exception: Prelude.Enum.succ{Int}: tried to take `succ' of maxBound
This suggests that we should abstract from the specific approach for determining whether one elements succeeds another:
chunksBy :: (a -> a -> Bool) -> [a] -> [Chunk a]
chunksBy succeeds = foldr go []
where
go x (Single y : Single z : cs) | y `succeeds` x && z `succeeds` y =
Range x z : cs
go x (Range y z : cs) | y `succeeds` x = Range x z : cs
go x cs = Single x : cs
Now, the version of chunks that was given above, can be expressed in terms of chunksBy simply by writing
chunks :: (Eq a, Enum a) => [a] -> [Chunk a]
chunks = chunksBy (\y x -> y == succ x)
Moreover, we can now also implement a version for bounded input types as well:
chunks' :: (Eq a, Enum a, Bounded a) => [a] -> [Chunk a]
chunks' = chunksBy (\y x -> x /= maxBound && y == succ x)
That merrily gives us:
> chunks' [maxBound, 1, 2, 3] :: [Chunk Int]
[9223372036854775807,1-3]
First, all elements of a list must be of the same type. Your resulting list has two different types. Ranges (for what ever that means) and Ints. We should convert one single digit into a range with lowest and highest been the same.
Been said so, You should define the Range data type and fold your list of Int into a list of Range
data Range = Range {from :: Int , to :: Int}
intsToRange :: [Int] -> [Range]
intsToRange [] = []
intsToRange [x] = [Range x x]
intsToRange (x:y:xs) = ... -- hint: you can use and auxiliar acc which holds the lowest value and keep recursion till find a y - x differece greater than 1.
You can also use fold, etc... to get a very haskelly point of view
Use recursion. Recursion is a leap of faith. It is imagining you've already written your definition and so can ("recursively") call it on a sub-problem of your full problem, and combine the (recursively calculated) sub-result with the left-over part to get the full solution -- easy:
ranges xs = let (leftovers, subproblem) = split xs
subresult = ranges subproblem
result = combine leftovers subresult
in
result
where
split xs = ....
combine as rs = ....
Now, we know the type of rs in combine (i.e. subresult in ranges) -- it is what ranges returns:
ranges :: [a] -> rngs
So, how do we split our input list xs? The type-oriented design philosophy says, follow the type.
xs is a list [a] of as. This type has two cases: [] or x:ys with x :: a and ys :: [a]. So the easiest way to split a list into a smaller list and some leftover part is
split (x:xs) = (x, ys)
split [] = *error* "no way to do this" -- intentionally invalid code
Taking note of the last case, we'll have to tweak the overall design to take that into account. But first things first, what's the rngs type could be? Going by your example data, it's a list of rngs, naturally, rngs ~ [rng].
A rng type though, we have a considerable degree of freedom to make it to be whatever we want. The cases we have to account for are pairs and singletons:
data Rng a = Single a
| Pair a a
.... and now we need to fit the jagged pieces together into one picture.
Combining a number with a range which starts from consecutive number is obvious.
Combining a number with a single number will have two obvious cases, for whether those numbers are consecutive or not.
I think / hope you can proceed from here.
If I have this code:
fun coord_select (x : int, cs : (int*int) list) =
List.filter (fn (first, _) => first = x ) cs
testing with input gives this:
coord_select (2, [(2,2),(2,3),(3,3),(4,3)])
: val it = [(2,2),(2,3)] : (int * int) list
Now, what if I don't give the desired first coordinate as an int but as a list of several required first coordinates such as [3,4], i.e., I want all coordinate tuples that start with 3 as well as 4? The easy way would simply to create a recursive wrapper around this that went through the list and plugged in the value as coord_select's first variable. But I would like to understand nested things better than such brute force. So I came up with this:
fun coord_match (fs : int list, cs :(int*int) list) =
map (coord_select (f, cs)) fs
but this can't really work because, as was pointed out, coord_select in the map is actually trying to return a list -- and how does map know to plug in the members of fs into f in the first place? Common Lisp does have a device to keep functions like this from running, i.e., the ' operator. But this wouldn't help, again, because map doesn't know which variable fs is supplying. For input, e.g., I have these coordinates:
[(2,2),(2,3),(3,3),(4,3)]
and I have this list of x-coordinates to match against the above list
[3,4]
Again, I could just put a recursive wrapper around this, but I'm reaching for a more elegant nested solution from the greater fold family.
what if I don't give the desired first coordinate as an int but as a list of several required first coordinates such as [3,4], i.e., I want all coordinate tuples that start with 3 and 4
It sounds like you want all coordinate tuples that start with 3 or 4, since a coordinate can't both be 3 and 4.
Given that, you can write coord_select like:
fun member (x, xs) =
List.exists (fn x2 => x = x2) xs
fun coord_select (xs, coords) =
List.filter (fn (x, _) => member (x, xs)) coords
the greater fold family
This family is called catamorphisms, of which map, filter, exists and foldl belong. Since foldl is the most general of these, it is technically possible to write the code above using folds entirely:
fun coord_select (xs, coords) =
foldr (fn ((x, y), acc1) =>
if foldl (fn (x2, acc2) => acc2 orelse x = x2) false xs
then (x, y) :: acc1
else acc1) [] coords
but as should be evident, explicit folds are not very readable.
If there's a specialised combinator that does a job, you would rather want that over a fold. And if it doesn't exist, creating it from slightly less specialised combinators improves readability. Folding is as close to manual recursion as you get and so provides little information to the reader about what kind of recursion we're attempting.
For that reason I also made member from exists, since exists requires me to specify a predicate and my predicate is "equality with x"; so even exists, I feel, adds clutter to the coord_select function.
You can learn more about list catamorphisms in functional programming by reading Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire (1991) by Meijer, Fokkinga, Paterson.
To put it straigth, I'm fairly new to Haskell and trying to solve a problem (programming exercise) I came over. Where it says I should create a function
com :: Int -> [t] -> [[t]]
that returns all possible choices of n elements, where n and list are the first and second arguments, respectively. Elements can be picked over again and in a different order. A result would be like:
com 2 [1,2,3] = [[1,1], [1,2]..[3,3]]
For the cases n = 1 and n = 2, I manage to solve the cases. The case n = 1 is quite simple, and, for the case n = 2, I would use concatenation and build it up. However, I don't understand how it can be made n-ary and work for all n. Like if suddenly a function call would be like com 10 ...
Is this what you want?
> sequence (replicate 3 "abc")
["aaa","aab","aac","aba","abb","abc","aca","acb","acc"
,"baa","bab","bac","bba","bbb","bbc","bca","bcb","bcc"
,"caa","cab","cac","cba","cbb","cbc","cca","ccb","ccc"]
The above exploits the fact that sequence, in the list monad, builds the cartesian product of a list of lists. So, we can simply replicate our list n times, and then take the product.
(Note that "abc" above is a shorthand for the list of charatcters ['a','b','c'])
So, a solution could be
com n xs = sequence (replicate n xs)
or equivalently, as Daniel Wagner points out below,
com = replicateM
A final note: I do realize that this is probably not very helpful for actually learning how to program. Indeed, I pulled two "magic" functions from the library which solved the task. Still, it shows how the problem can be reduced to two subproblems: 1) replicating a value n times and 2) building a cartesian product. The second task is a nice exercise on its own, if you don't want to use the library. You may wish to solve that starting from:
sequence :: [[a]] -> [[a]]
sequence [] = [[]]
sequence (x:xs) = ...
where ys = sequence xs
First: [] is a list constructor, not a tuple. I don't know any general way to build n-ary tuple.
However, sticking to lists, if you have n = 1 case solved and n = 2 case solved try to express the latter in term of the former. Then generalize to any n in terms of n-1:
com n xs = concat [map (x:) (com (n-1) xs) | x <- xs ]
A more verbose way to write it, but potentially more helpful when trying to understand List non-determinism and trying to understand exactly what the Haskell comprehension syntactic sugar really means, is to write with do notation:
com :: Int -> [a] -> [[a]]
com 0 _ = []
com 1 xs = [[x] | x <- xs]
com n xs = do
x <- xs
let ys = com (n - 1) xs
map (x:) ys
I want to make a program insertAt where z is the place in the list, and y is the number being inserted into the list xs. Im new to haskell and this is what I have so far.
insertAt :: Int-> Int-> [Int]-> [Int]
insertAt z y xs
| z==1 = y:xs
but I'm not sure where to go from there.
I have an elementAt function, where
elementAt v xs
| v==1 = head xs
| otherwise = elementAt (v-1) (tail xs)
but I'm not sure how I can fit it in or if I even need to. If possible, I'd like to avoid append.
If this isn't homework: let (ys,zs) = splitAt n xs in ys ++ [new_element] ++ zs
For the rest of this post I'm going to assume you're doing this problem as homework or to teach yourself how to do this kind of thing.
The key to this kind of problem is to break it down into its natural cases. You're processing two pieces of data: the list you're inserting into, and the position in that list. In this case, each piece of data has two natural cases: the list you're procssing can be empty or not, and the number you're processing can be zero or not. So the first step is to write out all four cases:
insertAt 0 val [] = ...
insertAt 0 val (x:xs) = ...
insertAt n val [] = ...
insertAt n val (x:xs) = ...
Now, for each of these four cases, you need to think about what the answer should be given that you're in that case.
For the first two cases, the answer is easy: if you want to insert into the front of a list, just stick the value you're interested in at the beginning, whether the list is empty or not.
The third case demonstrates that there's actually an ambiguity in the question: what happens if you're asked to insert into, say, the third position of a list that's empty? Sounds like an error to me, but you'll have to answer what you want to do in that case for yourself.
The fourth case is most interesting: Suppose you want to insert a value into not-the-first position of a list that's not empty. In this case, remember that you can use recursion to solve smaller instances of your problem. In this case, you can use recursion to solve, for instance, insertAt (n-1) val xs -- that is, the result of inserting your same value into the tail of your input list at the n-1th position. For example, if you were trying to insert 5 into position 3 (the fourth position) of the list [100,200,300], you can use recursion to insert 5 into position 2 (the third position) of the list [200,300], which means the recursive call would produce [200,300,5].
We can just assume that the recursive call will work; our only job now is to convert the answer to that smaller problem into the answer to the original problem we were given. The answer we want in the example is [100,200,300,5] (the result of inserting 5 into position 4 of the list [100,200,300], and what we have is the list [200,300,5]. So how can we get the result we want? Just add back on the first element! (Think about why this is true.)
With that case finished, we've covered all the possible cases for combinations of lists and positions to update. Since our function will work correctly for all possibilities, and our possibilities cover all possible inputs, that means our function will always work correctly. So we're done!
I'll leave it to you to translate these ideas into Haskell since the point of the exercise is for you to learn it, but hopefully that lets you know how to solve the problem.
You could split the list at index z and then concatenate the first part of the list with the element (using ++ [y]) and then with the second part of the list. However, this would create a new list as data is immutable by default. The first element of the list by convention has the index 0 (so adjust z accordingly if you want the meaning of fist elemnt is indexed by 1).
insertAt :: Int -> Int-> [Int] -> [Int]
insertAt z y xs = as ++ (y:bs)
where (as,bs) = splitAt z xs
While above answers are correct, I think this is more concise:
insertAt :: Int -> Int-> [Int]-> [Int]
insertAt z y xs = (take z xs) ++ y:(drop z xs)
Haskell
addm::[Int]->Int
addm (x:xs) = sum(x:xs)
I was able to achieve to get a sum of a list using sum function but is it possible to get the sum of a list using map function? Also what the use of map function?
You can't really use map to sum up a list, because map treats each list element independently from the others. You can use map for example to increment each value in a list like in
map (+1) [1,2,3,4] -- gives [2,3,4,5]
Another way to implement your addm would be to use foldl:
addm' = foldl (+) 0
Here it is, the supposedly impossible definition of sum in terms of map:
sum' xs = let { ys = 0 : map (\(a,b) -> a + b) (zip xs ys) } in last ys
this actually shows how scanl can be implemented in terms of map (and zip and last), the above being equivalent to foldl (+) 0 xs === last $ scanl (+) 0 xs:
scanl' f z xs = let { ys = z : map (uncurry f) (zip ys xs) } in ys
I expect one can calculate many things with map, arranging for all kinds of information flow through zip.
edit: the above is just a zipWith in disguise of course (and zipWith is kind of a map2):
sum' xs = let { ys = 0 : zipWith (+) ys xs } in last ys
This seems to suggest that scanl is more versatile than foldl.
It is not possible to use map to reduce a list to its sum. That recursive pattern is a fold.
sum :: [Int] -> Int
sum = foldr (+) 0
As an aside, note that you can define map as a fold as well:
map :: (a -> b) -> ([a] -> [b])
map f = fold (\x xs -> f x : xs) []
This is because foldr is the canonical recursive function on lists.
References: A tutorial on the universality and expressiveness of fold, Graham Hutton, J. Functional Programming 9 (4): 355–372, July 1999.
After some insights I have to add another answer: You can't get the sum of a list with map, but you can get the sum with its monadic version mapM. All you need to do is to use a Writer monad (see LYAHFGG) over the Sum monoid (see LYAHFGG).
I wrote a specialized version, which is probably easier to understand:
data Adder a = Adder a Int
instance Monad Adder where
return x = Adder x 0
(Adder x s) >>= f = let Adder x' s' = f x
in Adder x' (s + s')
toAdder x = Adder x x
sum' xs = let Adder _ s = mapM toAdder xs in s
main = print $ sum' [1..100]
--5050
Adder is just a wrapper around some type which also keeps a "running sum." We can make Adder a monad, and here it does some work: When the operation >>= (a.k.a. "bind") is executed, it returns the new result and the value of the running sum of that result plus the original running sum. The toAdder function takes an Int and creates an Adder that holds that argument both as wrapped value and as running sum (actually we're not interested in the value, but only in the sum part). Then in sum' mapM can do its magic: While it works similar to map for the values embedded in the monad, it executes "monadic" functions like toAdder, and chains these calls (it uses sequence to do this). At this point, we get through the "backdoor" of our monad the interaction between list elements that the standard map is missing.
Map "maps" each element of your list to an element in your output:
let f(x) = x*x
map f [1,2,3]
This will return a list of the squares.
To sum all elements in a list, use fold:
foldl (+) 0 [1,2,3]
+ is the function you want to apply, and 0 is the initial value (0 for sum, 1 for product etc)
As the other answers point out, the "normal" way is to use one of the fold functions. However it is possible to write something pretty similar to a while loop in imperative languages:
sum' [] = 0
sum' xs = head $ until single loop xs where
single [_] = True
single _ = False
loop (x1 : x2 : xs) = (x1 + x2) : xs
It adds the first two elements of the list together until it ends up with a one-element list, and returns that value (using head).
I realize this question has been answered, but I wanted to add this thought...
listLen2 :: [a] -> Int
listLen2 = sum . map (const 1)
I believe it returns the constant 1 for each item in the list, and returns the sum!
Might not be the best coding practice, but it was an example my professor gave to us students that seems to relate to this question well.
map can never be the primary tool for summing the elements of a container, in much the same way that a screwdriver can never be the primary tool for watching a movie. But you can use a screwdriver to fix a movie projector. If you really want, you can write
import Data.Monoid
import Data.Foldable
mySum :: (Foldable f, Functor f, Num a)
=> f a -> a
mySum = getSum . fold . fmap Sum
Of course, this is silly. You can get a more general, and possibly more efficient, version:
mySum' :: (Foldable f, Num a) => f a -> a
mySum' = getSum . foldMap Sum
Or better, just use sum, because its actually made for the job.