I have this haskell function that I don't quite understand.
ns :: [Integer]
ns = 0 : [n+k | (n, k) <- zip ns [1,3..]]
I am asked to "take 3 ns".
I thought ns was constant so it would only zip with the first element of the list, giving (0,1). Then when added gives an answer of 1. Then it says "take 3 ns" so I zipped 0 with the first 5 elements of the list, giving... (0,1),(0,3), (0,5) and then when added, I get a final answer of [1,3,5]. However this isn't the correct answer.
What is actually happening to ns? I'm struggling to understand...
haskell is lazy so you can have recursive definitions. Here it is laid out.
ns = 0 : something
(n,k) <- zip (0 : something ) [1,3,5,7...]
(n,k) <- [(0,1) : something )
ns = 0 : 1 : something
(n,k) <- zip ( 0 : 1 : something ) [3,5,7...]
(n,k) <- (0,1) : (1,3) : something
ns = 0 : 1 : 4 : something
(n,k) <- zip ( 0 : 1 : 4 : something ) [5,7...]
(n,k) <- (0,1) : (1,3) : (4,5) : something
ns = 0 : 1 : 4 : 9 : something
....
See how we determine what the next tuple is then add its two elements. This allows us to determine the next element.
Everything in Haskell is lazy, so while ns is constant, that doesn't mean items in the list can't be "added" (or more accurately, "computed") at a later time. Also, because ns is recursively defined, values that appear later in the list can depend on values that appear earlier in the list.
Let's go over this step by step.
First, we know that ns starts with 0, so for the time being, ns looks like this:
ns: 0, ?, ?, ...
So what's in the first question mark? According to your function, it's n + k, where n is the first element in ns, and k is the first element in [1, 3..]. So n = 0, k = 1, and n + k = 1.
ns: 0, 1, ?, ...
Moving on, the next element is also n + k, where we use the second elements of ns and [1, 3...]. We now know that the second element of ns is 1, so n = 1, k = 3, and n + k = 4.
ns: 0, 1, 4, ...
And so on.
Haskell evaluates things lazily, so it'll only compute exactly as much of a value is needed. That means we need to somehow need values of ns to see how it's computed.
head ns
head (0 : ...)
0
Clearly, head doesn't force enough for anything interesting to happen, but you can already see that the interesting part of ns is just discarded. That effect goes further when we ask for more, such as printing each element. Let's just force each element one after another to see the pattern. First, let's replace the list comprehension with a single equivalent function call
zipWith f [] _ = []
zipWith f _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
ns = 0 : zipwith (+) ns [1,3..]
Now we can evaluate elements of ns one by one. Really, to be more detailed, we're evaluating ns and determining that the first constructor is (:) and then deciding to evaluate the second argument to (:) as our next step. I'll use {...} to represent a not-yet-evaluated thunk.
ns
{ 0 } : zipWith (+) ns [1,3...]
{ 0 } : zipWith (+) ({ 0 } : { ... }) [1,3...] -- notice the { 0 } thunk gets evaluated
0 : { 0 + 1 } : zipWith f { ... } [3,5...]
0 : 1 : { 1 + 3 } : zipWith f { ... } [5,7...]
0 : 1 : 4 : { 4 + 5 } : zipWith f { ... } [7,9...]
What's important to note above is that since ns get evaluated only piece by piece, it never demands to know something that has not yet been computed. In this way, ns forms a tight, clever little loop all in itself.
That's equivalent to ns = 0 : (zipWith (+) ns [1,3,...]) , which may be easier to comprehend: the k+1th element is the kth element plus k-th odd number, with appropriate starting conditions.
ns :: [Integer]
ns = 0 : [n+k | (n, k) <- zip ns [1,3..]]
this is a corecursive data definition. ns is a constant, a list, but it is "fleshed out" by access, since Haskell is lazy.
An illustration:
1 n1 n2 n3 n4 n5 ... -- the list ns, [n1,n2,n3,...],
2 0 1 4 ... -- starts with 0
3 -----------------
4 1 3 5 7 9 -- [1,3..]
5 -----------------
6 1 4 ... -- sum the lines 2 and 4 pairwise, from left to right, and
7 n2 n3 n4 n5 ... -- store the results starting at (tail ns), i.e. from n2
We can see precisely how access is forcing the list ns into existence step by step, e.g. after print $ take 4 ns, by naming the interim entities:
ns :: [Integer]
ns = 0 : [n+k | (n, k) <- zip ns [1,3..]]
ns = 0 : tail1
tail1 = [n+k | (n, k) <- zip ns [1,3..]]
= [n+k | (n, k) <- zip (0 : tail1) [1,3..]]
= [n+k | (n, k) <- (0,1) : zip tail1 [3,5..]]
= 1 : [n+k | (n, k) <- zip tail1 [3,5..]]
= 1 : tail2
tail2 = [n+k | (n, k) <- zip (1 : tail2) [3,5..]]
= [n+k | (n, k) <- (1,3) : zip tail2 [5,7..]]
= 4 : tail3
tail3 = [n+k | (n, k) <- zip (4 : tail3) [5,7..]]
= 9 : tail4
tail4 = [n+k | (n, k) <- zip (9 : tail4) [7,9..]]
------
ns = 0 : 1 : 4 : 9 : tail4
Related
So I have to make a decimal number into binary list like so: intToBitString 4 = [1,0,0].
Which i have done like so:
intToBitString n = reverse (helper n)
helper 0 = []
helper n
| n `mod` 2 == 1 = 1 : helper (n `div` 2)
| n `mod` 2 == 0 = 0 : helper(n `div` 2)
But then I also have to make a function called intToByte, which pads out the list with 0-s until it's length is 8 elements long. (so making it a bytestring) Like this:
intToByte 7 = [0, 0, 0, 0, 0, 1, 1, 1]
I have tried so many things, but they never work. I am a beginner, so I only know the "if" loop the way I showed above, and recursion, but I dont know anything fancy. One of my tries:
intToByte 0 = [0]
intToByte n
| eight n == helper2 n = reverse (helper2 n)
| otherwise = eight n
helper2 0 = []
helper2 n
| n `mod` 2 == 1 = 1 : helper2 (n `div` 2)
| n `mod` 2 == 0 = 0 : helper2 (n `div` 2)
eight n
| length (helper2 n) < 8 = 0 : eight n
| otherwise = helper2 n
I have been working on this for so many hours that i'm getting confused by it. But this is part of an important assignment, so help would be very appreciated!
First of all, you can simplify your code with:
helper2 :: Integral i => i -> [i]
helper2 0 = []
helper2 n = r : helper2 q
where (q,r) = quotRem n 2
Secondly, the above is a big endian representation [wiki]. Indeed, 7 is represented as [1,1,1], whereas 14 is for example represented as [0,1,1,1]. If we want to revers this, we can work with an accumulator:
helper2 :: Integral i => i -> [i]
helper2 = go []
where go rs 0 = rs
go rs n = go (r:rs) q
where (q,r) = quotRem n 2
This thus maps 7 to [1,1,1] and 14 to [1,1,1,0]. But now we still need to add leading zeros. We can do that for example by maintaing the number of elements already added to the list:
eight :: Integral i => i -> [i]
eight = go [] 0
where go rs l 0 = replicate (8-l) 0 ++ rs
go rs l n = go (r:rs) (l+1) q
where (q,r) = quotRem n 2
Padding can be as simple as computing how many additional elements to push to the list and then have those elements produced using the function replicate from the Prelude:
padLeft :: Int -> a -> [a] -> [a]
padLeft n x xs = replicate (n - length xs) x ++ xs
For instance:
> padLeft 8 0 [1, 1, 0]
[0,0,0,0,0,1,1,0]
One approach would be to define a function bits such that bits k converts its argument to a bit string of length k:
bits :: Int -> Int -> [Int]
bits 0 _n = []
bits k n | n < 0 = error "bits: negative"
| n > 2 * m - 1 = error "bits: overflow"
| otherwise = let (i, j) = n `divMod` m in i : bits (k - 1) j
where m = 2 ^ (k - 1)
Your function eight is then easily written as
eight :: Int -> [Int]
eight = bits 8
This gives:
> eight 4
[0,0,0,0,0,1,0,0]
> eight 7
[0,0,0,0,0,1,1,1]
I find it really difficult to understand the mechanics of the following recursive function:
sums (x:y:ys) = x:sums(x + y : ys)
sums xs = xs
sums ([0..4])
Output:
[0, 1, 3, 6, 10]
What exactly happens in this line?:
x:sums(x + y : ys)
I would say that before the program can append the 'x' to the list, the function sum(x + y : ys) has to be executed first. But in that case, 'x' would be appended to the list only once - at the end of the recursion loop - which wouldn't result in the given output... so where are the flaws in my logic?
My follow-up question: how should I look at/treat recursive functions in a logical way, that will (hopefully) lead me to an 'aha-erlebnis'?
Any help is much appreciated!
You can understand Haskell code by stepwise reduction. Maybe the following example reduction sequence helps with your aha.
(A Haskell implementation actually does something related to such reduction steps, but maybe in a different order. You get the same end result, though).
In this example, you start with:
sums [0..4]
Expand the [0..4] notation a bit:
sums (0 : 1 : [2..4])
Now we see that the first equation of sums matches, with x = 0, y = 1, and ys = [2..4]. So we get:
0 : sums (0 + 1 : [2..4])
We can compute 0 + 1:
0 : sums (1 : [2..4])
And expand [2..4] a bit:
0 : sums (1 : 2 : [3..4])
Now we see that the first equation of sums matches again, this time with x = 1, y = 2, and ys = [3..4]. So we get:
0 : 1 : sums (1 + 2 : [3..4])
We can compute 1 + 2:
0 : 1 : sums (3 : [3..4])
And expand [3..4] a bit:
0 : 1 : sums (3 : 3 : [4..4])
Now we see that the first equation of sums matches again, this time with x = 3, y = 3, and ys = [4..4]. So we get:
0 : 1 : 3 : sums (3 + 3 : [4..4])
We can compute 3 + 3:
0 : 1 : 3 : sums (6 : [4..4])
And expand [4..4]:
0 : 1 : 3 : sums (6 : 4 : [])
Now we see that the first equation of sums matches again, this time with x = 6, y = 4, and ys = []. So we get:
0 : 1 : 3 : 6 : sums (6 + 4 : [])
We can compute 6 + 4:
0 : 1 : 3 : 6 : sums (10 : [])
This time, the first equation for sums doesn't match. But the second equation matches. So we get:
0 : 1 : 3 : 6 : 10 : []
This is the observed output [0, 1, 3, 6, 10].
This is no different than recursion in any other langauge. When sums [0..4] (the parentheses are unnecessary) is first called, x==0, y==1, and ys == [2..4]. Thus, the return value is a new list created from 0 and sums [1..4].
In a strict language, the recursive call would complete before finally creating the new list. Since Haskell is lazy, a list starting with 0 and continuing with a promise to evaluate sums [1..4] is returned. The recursive call won't actually be evaluated until someone actually tries to access the tail of the list.
You could notice that
sums (x:y:ys) = x:sums(x + y : ys)
is equivalent to
sums (x:y:z:ys) = x:x+y:sums(x+y+z : ys)
sums (x:y:ys) = x:sums(x + y : ys)
and (with more than 2 items) is also equivalent to
sums (x:y:z: w: ys) = x:x+y:x+y+z:sums(x+y+z +w: ys)
sums (x:y:z:ys) = x:x+y:sums(x+y+z : ys)
sums (x:y:ys) = x:sums(x + y : ys)
so by induction you have that
sums(1:2:3:4 :[])
is equal to
1 : 1 + 2 : 1 + 2 + 3 : 1 + 2 + 3 + 4 : []
Based on the above you can also predict that with
fact(x:y:ys) = x: fact(x * y : ys)
fact(xs) = xs
then
fact([1..4])
is
1:1*2:1*2*3:1*2*3*4:[]
There are two equation that define the function sums. Keep rewriting an expression that involves sums using the first equation that matches the argument, or other suitable equations (like 1+2=3).
sums [0..4] =
-- by syntactic sugar
sums (0:1:2:3:4:[]) =
-- by eq. 1, x=0,y=1,ys=2:3:4:[]
0 : sums ((0+1) : 2 : 3:4:[]) =
-- by addition
0 : sums (1 : 2 : 3:4:[]) =
-- by eq. 1, x=1, y=2, ys=3:4:[]
0 : 1 : sums ((1+2) : 3 : 4:[]) =
-- by addition
0 : 1 : sums (3 : 3 : 4:[]) =
-- by eq. 1, x=3, y=3, ys=4:[]
0 : 1 : 3 : sums ((3+3) : 4 : []) =
-- by addition
0 : 1 : 3 : sums (6 : 4 : []) =
-- by eq. 1, x=6, y=4, ys=[]
0 : 1 : 3 : 6 : sums ((6+4):[]) =
-- by addition
0 : 1 : 3 : 6 : sums (10:[]) =
-- by eq 2,xs=(10:[])
0 : 1 : 3 : 6 : 10 : [] =
-- by syntactic sugar
[0,1,3,6,10]
How to calculate the length of a list with a condition on members?
Generally, the following is used to compute the length of a list
(* Compute the length of a list *)
fun length(L) =
if null L then 0
else 1 + length (tl (L));
but how to specify the range of member by counting only between 5 and 10?
If I want to use function foldr for question 1, how to do so?
In the lambda function for List.foldr, you should add 1 to the total if the element matches the condition, but 0 if it doesn't. This way, you can keep track of the number of elements that matches your condition.
val xs = [1,3,5,8,6,9,10,14,13,16,15]
val len = List.foldr (fn (x, t) => (if x > 5 andalso x < 15 then 1 else 0) + t) 0 xs
This is what you get when you run it:
val xs = [1,3,5,8,6,9,10,14,13,16,15] : int list
val len = 6 : int
I am trying to write a function
row :: Int -> Int -> [Int]
row n v
that returns a list of n integers, all 0's, except for the vth element, which needs to be a 1.
For instance,
row 0 0 = []
row 5 1 = [1,0,0,0,0]
row 5 3 = [0,0,1,0,0]
I am new to Haskell and having a lot of difficulty with this. In particular I can't figure out how to make it repeat 0's. I understand the concept of building a list from let's say [1..n], but I just get [1,2,3,4,5]
Any help with this would be greatly appreciated. Thank you.
Try:
let row n v = map (\x -> if x == v then 1 else 0) [1..n]
Here a "monadic" solution:
row n v = [(v-1, 0), (1, 1), (n-v, 0)] >>= (uncurry replicate)
The replicate function repeats a given value a number of times, e.g. replicate (v-1) 0 gives a list of v-1 zeros. The uncurry is used to modify the replicate in order to accept a tuple instead of two single arguments. The funny operator >>= is the heart of a monad; for lists it is the same as concatMap with flipped arguments.
With a comprehensive list :
row n v = [if x == v then 1 else 0 | x <- [1..n]]
Or using fromEnum (thanks dave4420)
row n v = [fromEnum (x == v) | x <- [1..n]]
This should also work:
row n v = replicate (v-1) 0 ++ [1] ++ replicate (n-v) 0
And yet another solution, recursively building up the list:
row :: Int -> Int -> [Int]
row 0 _ = []
row n 1 = 1 : (row (n-1) 0)
row n m = 0 : (row (n-1) (m-1))
And a more readable one, where zeros are "taken":
row :: Int -> Int -> [Int]
row 0 _ = []
row n m = take (m - 1) zeros ++ [1] ++ take (n - m) zeros
where zeros = (iterate id 0)
A simple recursive loop with two temporary variables c and lst . c is for counting and lst is list which we have to return.
row :: Int -> Int -> [ Int ]
row 0 0 = []
row n v = rowHelp n v 1 [] where
rowHelp n v c lst
| c > n = lst
| v == c = rowHelp n v ( c + 1 ) ( lst ++ [ 1 ] )
| otherwise = rowHelp n v ( c + 1 ) ( lst ++ [ 0 ] )
~
~
the fun with haskell is that it let's you write your program very much the way you would express the algorithm. So try:
row n v = [if (x `mod` v==0) then 1 else 0 | x <- [1..n] ]
At first you create a list from 1,2 to n.
Then you check if the number is divisible by v, if it is, 1 is inserted in the output list, if not 0.
Examples:
> row 0 0
[]
> row 5 1
[1,0,0,0,0]
> row 5 3
[0,0,1,0,0]
> row 15 3
[0,0,1,0,0,1,0,0,1,0,0,1,0,0,1]
HTH Chris
I like to demonstrate a top down approach, based on Chris's solution:
row n v = result
where
result = take n numbers -- our result will have a length of n
numbers = map trans [1,2,..] -- and is some transformation of
-- the list of natural numbers
trans e
| e `mod` v == 0 = 1 -- let every v-th element be 1
| otherwise = 0 -- 0 otherwise
This style emphasizes the idea in functional programming that one writes down what a certain value like row n v is supposed to be, rather than trying to write down what a function does. In reminiscence of a well known joke about the lesser known pragramming language Sartre one could say that in pure functional programming functions do nothing, they just are.
I have datatype:
data SidesType = Sides Int Int Int deriving (Show)
And I need a function which get a list of SidesType and remove duplicates from it.
*Main> let a = [Sides 3 4 5,Sides 3 4 5,Sides 5 12 13,Sides 6 8 10,Sides 6 8 10,Sides 8 15 17,Sides 9 12 15,Sides 5 12 13,Sides 9 12 15,Sides 12 16 20,Sides 8 15 17,Sides 15 20 25,Sides 12 16 20,Sides 15 20 25]
*Main> removeDuplicateFromList [] a
[Sides 3 4 5,Sides 5 12 13,Sides 6 8 10,Sides 6 8 10,Sides 8 15 17,Sides 9 12 15,Sides 5 12 13,Sides 9 12 15,Sides 12 16 20,Sides 8 15 17,Sides 15 20 25,Sides 12 16 20,Sides 15 20 25]
Here is my solution:
removeElementFromList :: [SidesType] -> SidesType -> [SidesType]
removeElementFromList lst element =
let (Sides a b c) = element
in [(Sides x y z) | (Sides x y z) <- lst, (x /= a) || (y /= b)]
removeDuplicateFromList :: [SidesType] -> [SidesType] -> [SidesType]
removeDuplicateFromList inlist outlist
| (length outlist) == 0 = inlist
| otherwise =
let element = head outlist
b = tail outlist
filtered = removeElementFromList b element
in removeDuplicateFromList (inlist ++ [element]) filtered
I am just wondering if there is any other way to write this code in more haskell-way ?
As usual there is "By" function which adds flexibility:
nubBy :: (a -> a -> Bool) -> [a] -> [a]
PS Although it's O(n^2)
You're already deriving Show for your datatype. If you also derive Eq, you can use nub from module Data.List.
Use Data.List.nub
First derive the order class also:
data XYZ = XYZ .... deriving (Show, Eq, Ord)
Or write your on Eq instance:
instance Eq XYZ where
a == b = ...
Then be intelligent and use a Tree! [Computer Science Trees grow from top to bottom!][1]
import qualified Data.Map.Strict as Map
removeDuplicates ::[a] -> [a]
removeDuplicates list = map fst $ Map.toList $ Map.fromList $ map (\a -> (a,a)) list
Complexity (from right to left) for list with length N:
map of the list: O(N)
Map.fromList: O(N*log N)
Map.toList: O(log N)
map over list with list length smaller or equal to N: O(N)
They are called consecutively, this means, there are pluses between the complexities of the parts => O(2 * N + N * log N + log N) = O(N * log N)
This is way better than traversing N^2 times over the list!
See: wolframAlpha plots. I included 2*N also for comparison reasons.
2+3: http://hackage.haskell.org/package/containers-0.5.4.0/docs/Data-Map-Strict.html
[1]: Search wikipedia for Computer Science Tree