From this Youtube video:
> let loeb fs = xs where xs = fmap ($ xs) fs
> loeb [length, (!! 0)]
[2,2]
The xs here is recursively defined, and how loeb terminates is beyond me.
try it:
loeb [length, (!! 0)]
= xs where xs = fmap ($ xs) [length, (!! 0)]
= xs where xs = [length xs, xs !! 0]
so of course length xs is just 2, and so the first element of xs (length xs) is 2 as well.
remember: length xs does not need to evaluate the items of the list:
length [undefined, undefined] = 2
The reason is that length does not evaluate the elements of the list. It simply counts the elements. length is (semantically equivalent) defined as:
length (_:xs) = 1 + length xs
length _ = 0
Even if one of the elements thus comes down on calculating an expression that results in an infinite loop, that doesn't matter. Al long as the list itself is not infinite of course.
Now of you call loeb [length, (!! 0)], it will be evaluated as:
loeb [length, (!! 0)]
xs = fmap ($ xs) [length,(!! 0)]
xs = [length xs,xs !! 0]
Thus the length xs performs lazy evaluation: it is not interested in the value of the elements, so they remain unsolved when counting.
Related
Input: List xs with arbitrary numeric elements, xs has at least two elements / Output: smallest distance between adjacent elements in the list.
-- Input: List xs with at least two numeric elements & its implementation an end recursive function.
-- Erg: Returns the smallest distance of adjacent elements from the output list.
minimumdistance :: [Int] -> Int
minimumdistance [] = error "Empty list".
minimumdistance [_] = error "Requirement is not met".
minimumdistance [a,b] = abs (a - b)
minimaldistance (x:y:xs) = helper (abs (x - y)) xs where
helper :: Int -> [Int] -> Int
helper acc [] = acc
helper acc (z:zs) = if (abs (y - z)) < acc then helper (abs (y - z)) zs else helper
acc zs
Is the function endrecursive because that we are supposed to solve the task endrecursive and I am sure because I do not have the definition yet correctly, but I also on other pages, the endrecursive representation not understood
Your code has several issues mentioned in comments.
I suggest you break this down into smaller problems. We can write a tail-recursive function to get pairs of adjacent numbers from the list.
pairs [] = error "Not long enough"
pairs [_] = error "Not long enough"
pairs lst = aux lst []
where
aux (a:b:c) acc = aux (b:c) ((a, b):acc)
aux _ acc = acc
Now, if we test this:
ghci> pairs [1, 3, 6, 7, 10]
[(7,10),(6,7),(3,6),(1,3)]
We can use map to get the differences.
ghci> map (\(a, b) -> abs (a - b)) $ pairs [1, 3, 6, 7, 10]
[3,1,3,2]
Now we just need to reduce that down to the minimum.
ghci> foldl1 min $ map (\(a, b) -> abs (a - b)) $ pairs [1, 3, 6, 7, 10]
1
In your code for the helper function, the y variable does not get updated at all. Hence it remains equal to the second element of the initial input list in all successive scopes. This is probably not what you want.
It is more reliable to just include the previous list element into your state/accumulator, together with the smallest distance seen so far. This gives the following code:
minimumDistance :: [Int] -> Int
minimumDistance [] = error "Empty list."
minimumDistance [_] = error "Requirement is not met."
minimumDistance (x:y:xs) = helper (abs (x-y), y) xs where
helper (mnd,u) [] = mnd
helper (mnd,u) (z:zs) = let d1 = abs (u-z)
in if (d1 < mnd) then helper (d1, z) zs
else helper (mnd, z) zs
Sanity check:
We can generate a small random list, and compare the result of our minimumDistance function with the one obtained by just combining a few suitable library functions. Like this:
$ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/ :? for help
...
λ>
λ> :load q75011741.hs
[1 of 1] Compiling Main ( q75011741.hs, interpreted )
Ok, one module loaded.
λ>
λ> :type minimumDistance
minimumDistance :: [Int] -> Int
λ>
λ> import System.Random (randomRs, mkStdGen)
λ>
λ> g0 = mkStdGen 42
λ>
λ> xs = take 20 $ randomRs (0,500) g0
λ>
λ> xs
[48,151,95,271,208,466,401,23,139,95,500,306,187,389,398,297,248,94,348,91]
λ>
λ> minimumDistance xs
9
λ>
λ>
λ> zip xs (tail xs)
[(48,151),(151,95),(95,271),(271,208),(208,466),(466,401),(401,23),(23,139),(139,95),(95,500),(500,306),(306,187),(187,389),(389,398),(398,297),(297,248),(248,94),(94,348),(348,91)]
λ>
λ> map (\(a,b) -> abs(a-b)) $ zip xs (tail xs)
[103,56,176,63,258,65,378,116,44,405,194,119,202,9,101,49,154,254,257]
λ>
λ> minimum $ map (\(a,b) -> abs(a-b)) $ zip xs (tail xs)
9
λ>
So it looks OK.
Side note:
If for comparison purposes one also wants a solution based on a library-provided recursion scheme, the foldl' library function can be used. This gives the following code change:
minimumDistance (x:y:xs) = fst $ foldl' sfn acc0 xs where
acc0 = (abs(x-y), y)
sfn (mnd, pv) z = let d1 = abs (pv-z) in if (d1 < mnd) then (d1, z)
else (mnd, z)
I'm working on UPENN Haskell Homework 6 Exercise 5, trying to define a ruler function
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,...
where the nth element in the stream (assuming the first element corresponds to n = 1) is the largest power of 2 which evenly divides n.
I just came up with an idea to build it without any divisibility testing:
data Stream x = Cons x (Stream x) deriving (Eq)
streamRepeat x = Cons x (streamRepeat x)
interleaveStreams (Cons x xs) (Cons y ys) =
Cons x (Cons y (interleaveStreams xs ys))
ruler =
interleaveStreams (streamRepeat 0)
(interleaveStreams (streamRepeat 1)
(interleaveStreams (streamRepeat 2)
(interleaveStreams (streamRepeat 3) (...))
where first 20 element of
ruler =
interleaveStreams (streamRepeat 0)
(interleaveStreams (streamRepeat 1)
(interleaveStreams (streamRepeat 2)
(interleaveStreams (streamRepeat 3) (streamRepeat 4))))
is
[0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2]
Obviously I couldn't define it manually to infinite so I defined a infInterStream to help such infinite recursion definition:
infInterStream n = interleaveStreams (streamRepeat n) (infInterStream (n+1))
ruler = infInterStream 0
But now I get stuck when typing in ruler in ghci, it probably falls into infinite loop.
It shouldn't be if lazy evaluation works. I want to know why lazy evaluation fails here.
Helper function to observe Stream:
streamToList (Cons x xs) = x : streamToList xs
instance Show a => Show (Stream a) where
show = show . take 20 . streamToList
Your interleaving function is too strict. The following works:
interleaveStreams (Cons x xs) ys = Cons x (interleaveStreams ys xs)
This also works:
interleaveStreams (Cons x xs) ~(Cons y ys) =
Cons x (Cons y (interleaveStreams xs ys))
The original definition goes into infinite loop because interleaveStreams demands that both arguments must be of Cons forms. infInterStream n evaluates to the the interleaving of two streams, and the first one can be immediately evaluated to Cons, but the second one must also be reduced first to Cons, so we recursively call infInterStream (n + 1), which keeps calling itself ad infinitum.
If interleaveStreams can return a Cons a _ without first having to force the second argument, infInterStream can also incrementally build the result.
There's no need for a new type for streams, and we can just use Haskell's lazy lists instead. As others have noted, the definition of interleave must be sufficiently lazy that it can produce the first element of the output before testing whether the second argument is non-empty. This definition will do:
interleave (x:xs) ys = x : interleave ys xs
If you want interleave to work also for finite lists, you can add the equation
interleave [] ys = ys
Note also that, using functions from the standard prelude,
ruler = interleave (repeat 0) (map (+1) ruler)
Here repeat 0 is the list [0, 0, 0, ...].
I want to reorder a list in the following way:
[5,6,7,8,9] -> [7,5,9,6,8]
[6,7,8,5,4,3] -> [8,5,6,3,7,4]
It's supposed to get the middle number or numbers of the list and put them in the starting position. After that it should start to get the two outer numbers of the list and add them in and work its way in.
I have the following code to get the middle numbers and put them into the beginning of the list but can't figure out how to start adding the outer numbers into the new list.
-- import Data.List
-- import System.IO
longitude xs = length xs
middle xs = length xs `div` 2
addOne xs = middle xs - 1
oneMore xs = length xs - 1
otherCase xs = oneMore xs `div` 2
valuea xs = xs !! middle xs
valueb xs = xs !! addOne xs
valuec xs = xs !! otherCase xs
modulus xs = longitude xs `mod` 2
order xs = midNums xs
takes xs = take (otherCase xs) xs
oddOne xs = otherCase xs + 1
takeX xs = drop (oddOne xs) xs
value xs = takes xs ++ takeX xs
reorder xs = drop (otherCase xs )(take (middle xs + 1) xs)
valueOdd xs = reorder xs ++ takes xs ++ takeX xs
paruno xs = drop (middle xs + 1) xs
pairTwo xs = take (addOne xs) xs
midPair xs = take (addOne xs)(drop (middle xs -1) xs)
--Get the numbers
midNums xs = if modulus xs == 0 then midPair xs ++ paruno xs ++ pairTwo xs
else valueOdd xs
I want it to work like this: Demo
Try this:
f :: (Num a) => [a] -> [a]
f [] = []
f [x] = [x]
f xs = if len `mod` 2 == 1 then flatten [xs !! half] else flatten [xs !! (half-1), xs !! half]
where len = length xs
half = len `div` 2
firsthalf = take (half-1) xs
secondhalf = (reverse . take half . drop (half+1)) xs
outtoin = zipWith (\x y -> x:y:[]) firsthalf secondhalf
flatten = concat . flip (:) outtoin
Breaking it down:
First get the midpoint(s)
Next get the two halves of the list excluding middle elements
Build the list from outside inwards using zip
Concatenate the zip result to flatten and add to the middle elements list
Demo
So I have found that the built-in splitAt function in Haskell can be defined as follows:
splitAt :: Int -> [a] -> ([a], [a])
-- Pre: n >= 0
splitAt n []
= ([], [])
splitAt n (x : xs)
= if n == 0
then ([], x : xs)
else (x : xs', xs'')
where
(xs', xs'') = splitAt (n - 1) xs
What I don't understand here/can't get my head around is the where part.
As an example,
splitAt 2 "Haskell" should return (["Ha"],["skell"]), but I don't really understand how it works here to define (x:xs',xs'') as another function? How would this look like visually?
With the example:
splitAt 2 "Haskell"
= (('H':xs',xs''))
^ so this then does splitAt 1 "askell", but I'm very confused as to what happens to the xs',xs'' in the tuple above...
Thanks.
(xs', xs'') = splitAt (n - 1) xs
This takes the result of splitAt (n - 1) xs, which is a pair, and assigns the name xs' to the first element of that pair (i.e. the first n - 1 elements of xs) and xs'' to the second element (i.e. the remaining elements).
(x:xs', xs'')
This produces a pair. The first element of that pair is a list that's the result of prepending x to xs' (i.e. to the first n-1 elements of xs). The second element is xs'' (i.e. the remaining elements of xs).
So I'm learning haskell right now, and I'm having trouble understanding what I'm doing wrong for the following function that emulates zip
1.ziplike xs ys = [(x,y)|c<-[0..(min (length xs) (length ys))-1],x<-xs!!c,y<-ys!!c]
2.ziplike xs ys = [(xs!!c,ys!!c)|c<-[0..(min (length xs) (length ys))-1]]
Now, I know that the correct answer is number 2, but I don't understand why number 1 is wrong for the call ziplike [1,2,3] ['a', 'b', 'c', 'd']. I THINK it's because it's trying to select the index for an individual char, but I'm not sure why.
The error is "Couldn't match expected type ‘[t1]’ with actual type ‘Char’"
To a first approximation:
If e::[a],
and x <- e appears to the right of the | in a list comprehension,
then x :: a wherever it is bound.
This leads to a bit of a problem in your case. You have ys :: [Char] and c :: Int, so that ys!!c :: Char. Hence:
We have ys!!c :: Char
and y <- ys!!c appears to the right of the | in a list comprehension,
so y :: ??? wherever it is bound.
But now we are stuck when trying to write the conclusion about what type y should have: Char is not a list of as, no matter what a we pick.
There are several possible fixes; one is to use let instead of <-, as in
ziplike xs ys = [(x,y)|c<-[0..min (length xs) (length ys)-1],let x=xs!!c; y=ys!!c]
It's a type error.
When you write "x from xs get-index c" (i.e. x <- xs !! c) the thing that you are getting "from" xs !! c is not necessarily a list. It's a technical detail, but it's important. The "from" arrow comes from monad syntax/do-notation. A list comprehension is actually just a do-expression specialized to the List monad; so the right hand side of an arrow <- needs to be a list in the List monad.
You can fix this, first off, by "cheating" with singleton lists, a la:
ziplike xs ys = [ (x,y) | c <- [0 .. min (length xs) (length ys) - 1],
x <- [xs !! c],
y <- [ys !! c]]
So these left-arrows are not "let" variable bindings, but they make Cartesian products: but the Cartesian product of n things with 1 thing with 1 thing is just n * 1 * 1 == n things. So this is great, if a little weird and possibly inefficient.
To do what you were trying to do (bind x and y inside of the list comprehension) you could also write something like:
ziplike xs ys = [let x = xs !! c; y = ys !! c in (x, y)
| c <- [0 .. min (length xs) (length ys) - 1]]
-- or --
ziplike xs ys = [(x, y)
| c <- [0 .. min (length xs) (length ys) - 1],
let x = xs !! c, let y = ys !! c]
-- or --
ziplike xs ys = [(x, y)
| c <- [0 .. min (length xs) (length ys) - 1],
let x = xs !! c; y = ys !! c]
Notice that these are all do-notation ideas tacked together with commas. Of course all of these look more clumsy than
ziplike xs ys = [(xs !! c, ys !! c) | c <- [0..min (length xs) (length ys) - 1]
which does the exact same thing.
With that said, all of this stuff is much more inefficient than the zip function's recursive character: if I double the size of the list, your implementations take 4 times as long to process the whole list; zip only takes twice as long. So be mindful of this "hidden O(n2) factor" in your programming.