I have some Haskell code and need to write down Leftmost-innermost (call by value) and outermost (call-by-name):
second :: [Int] -> Int
second [] = 0
second (_:[]) = 0
second (_:x:xs) = x
doubleEach :: [Int] -> [Int]
doubleEach [] = []
doubleEach (x:xs) = x * 2 : (doubleEach xs)
repeat :: Int -> Int -> [Int]
repeat x n = if n > 0 then x : (repeat x (n-1)) else []
repeat ( second (doubleEach [2,3,5] )) ( second [3, 1, 4] )
innermost (call-by-value):
1. repeat (second (doubleEach [2,3,5] )) (second [3,1,4])
2. repeat (second 4 : doubleEach [3,5])) (1)
3. repeat (second (4 : 6 : d [5])) (1)
4. repeat (second ( 4 : 6 : 10 )) (1)
5. repeat (6) (1)
6. [6]
Question: How can I get outermost (call-by-name) stept by step evaluation? I do not understand how I can do that if repeat needs specified values to work and they are not given until the inner part is not evaluated.
How can I get outermost (call-by-name) stept by step evaluation? I do not understand how I can do that if repeat needs specified values to work and they are not given until the inner part is not evaluated.
You don't need the values to expand the function call - you can just pass in the unevaluated expressions. And then you only evaluate those expressions when it's necessary for ifs, pattern matches or primitive functions. That's how call-by-name evaluation works.
So your first step would be to take the body of repeat, replace each occurrence of x with second (doubleEach [2,3,5]) and each occurrence of n with second [3, 1, 4]. Then you'll need to evaluate the if condition and then you proceed with the body of the if.
Related
xs = [1, 2] ++ undefined
length $ take 2 $ take 4 xs
My brain is reading this as
length (take 2 ( take 4 xs ) )
If everything in the parenthesis is evaluated first, then why does this not error out with Exception: prelude.undefined?
The answer given by the book is that take 2 is only taking the first two indices, but shouldn't the take 4 take precedence here and get evaluated first?
If everything in the parenthesis is evaluated first, then why does this not error out with Exception: prelude.undefined?
Because Haskell is lazy. That means it does not evaluate anything unless it is necessary.
Indeed, length will need access to the list (but not to its elements if these contain calculations). It will thus ask the take 2 ( take 4 xs ) ) for the first elements, and then the second, and then the third, etc.
Now take is lazy as well. It means as long as it does not need to be evaluated, it will do nothing. In case the length asks the next element it will determine that element, if later another element is asked, it will provide the second element for the list. If the length asks for another one, then take 2 will stop, and thus return the empty list.
Haskell thus has not an evaluation strategy like Python or Java where the innermost functions are first evaluated and left to right.
Let's calculate! What is [1, 2] ++ undefined? Well, to know that, we first need to know what [1, 2] is. It's really just syntactic sugar for 1:2:[].
Next, we need to know what ++ is. The source code tells us:
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x : xs) ++ ys = x : xs ++ ys
Okay. So let's pattern match.
(1:2:[]) ++ undefined
= -- the second pattern matches
1 : (2:[]) ++ undefined
= -- the second pattern matches
1 : 2 : [] ++ undefined
= -- the first pattern matches
1 : 2 : undefined
Okay, so we've figured out that
xs = 1 : 2 : undefined
What about take 4 xs? Well, we first have to look at what take does. The real source code is somewhat complicated for performance reasons, but we can use this simpler, equivalent, version:
take :: Int -> [a] -> [a]
take n _ | n <= 0 = []
take _ [] = []
take n (a : as) = a : take (n - 1) as
So
take 4 xs
= -- value of xs
take 4 (1:2:undefined)
= -- 4 is positive, so the first guard falls through.
-- the second pattern fails (the list isn't empty)
-- the third pattern succeeds
1 : take 3 (2:undefined)
= -- same analysis
1 : 2 : take 3 undefined
= -- 3 is positive, so the guard fails.
-- the pattern match on undefined produces undefined
1 : 2 : undefined
That's just the same as xs!
Next we calculate
take 2 (take 4 xs)
= -- as shown above
take 2 (1 : 2 : undefined)
= -- following the same sequence above
1 : take 1 (2 : undefined)
= -- same same
1 : 2 : take 0 undefined
= -- this time the guard succeeds!
1 : 2 : []
= -- reinstalling syntactic sugar
[1, 2]
So now you have a fully defined list of two elements, and taking its length poses no special challenge at all.
Note that the above is a calculation. It does not represent the actual sequence of operations that occur when the program runs. But ... that doesn't actually matter. One of the great things about Haskell is that in your analysis, you can "substitute equals for equals" whenever you want. It won't affect the result. You do have to be a bit careful, however, not to let it confuse you. For example, suppose you want to evaluate null (repeat ()). You'd start out something like this:
repeat () = () : repeat ()
What do you do next? Well, one option is to continue to expand repeat ():
repeat () = () : () : repeat ()
It's totally valid. But if you keep going on that way forever, you'll never get to an answer. At some point, you have to look at the rest of the problem.
null (() : repeat ())
is immediately False. So just because you can find an infinite sequence of reductions doesn't mean there's an infinite loop. Indeed, the way Haskell works, there's only an infinite loop if every possible sequence of reductions is infinite.
Because you're not forcing the thunk after take 4 xs. Consider the following code in the repl
Prelude> xs = [1, 2] ++ undefined
Prelude> take 4 xs
[1,2*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries\base\GHC\Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:1:16 in interactive:Ghci1
This happens because of the implicit show in GHCi. But what if we don't use a bare expression?
Prelude> xs = [1, 2] ++ undefined
Prelude> ys = take 4 xs
Hey look no error! Let's keep going
Prelude> xs = [1, 2] ++ undefined
Prelude> ys = take 4 xs
Prelude> zs = take 2 ys
Prelude> length zs
2
sum :: [Int] -> Int
sum [] = 0
sum (x:xs) = x + sum xs
I do not understand what the purpose of the line sum [] = 0 is. I found this piece of code in a textbook (it did not go into detail as to what this line does.)
sum [] = 0 is the edge condition of the recursion.
Suppose we have sum [1, 4, 6, 8]. The list can be rewritten as 1:4:6:8:[]. The empty list is the last 'element'. The calculation is as follow (1 + ( 4 + (6 + ( 8 + 0)))). When all the elements of the list have been traversed, what remains is the empty list. Adds zero to the calculated result and ends the iteration.
Given a finite list of 0 and 1, how can I convert them to their integer value using first order function?
The head of the list is the least significant digit. For instance, 1011 evaluates to 13.
In this problem, I struggle to find both the recursive step and the base step because all depends wether it's a 0 and 1.
EDIT :
The goal is to define a function that will compute the decimal value given a binary string. An empty list should return 0 I guess, so it would be the base case.
Wrapping up my comments:
convert :: [Int] -> Int
convert [] = 0
convert (x : xs) = x + 2 * convert xs
The base case is the empty list, returning 0.
The recursive case follows from the fact that x is the least significant digit. convert xs (the recursive call) gives us the result for the tail of the list; to get the result of the whole list we need to multiply by 2 (to "shift over" the digits) and add x (0 or 1).
Here's my initial thoughts about how to handle this situation.
import Data.Char (digitToInt)
myFunction :: String -> Int
myFunction = foldr step 0
where step x y = (+) (digitToInt x) ( (*) y 2 )
Assuming the input is a list of 1s and 0s.
bin2num :: [Int] -> Int
bin2num list = go list 0
where go [] _ = 0
go (x:xs) n = (x*(2^n)) + (go xs (n+1))
Just double the acc and add it to the new element of the list . Easily use digitToInt to get the right list from the string _ st here . and foldl' for efficiency. This is Sanaz's answer
fromBin st = foldl' (\x acc -> x * 2 + acc ) 0 (map (digitToInt) st)
Trying to double elements of a list that are greater than 5 for example.
to double every element in a list i would do this
doubleAll n = [2*x| x <-n]
now i want to double all elements in list that are greater than 5 using list comprehensions.
So if i do this
doubleAll n = [2*x| x <-n, x>5]
My list [1,2,3,4,5] would result in to [10]. But i want my list to show [1,2,3,4,10]
Can anyone explain what i did wrong and how can this be fixed?
An interpretation of [2*x| x <-n, x>5] is:
Take the next element from n and call it x
Proceed if x>5, otherwise go to step 1
Return the value 2*x as the next element of the list.
Repeat
From this it is clear that the x>5 filters out elements of n. The expression is equivalent to:
map (\x -> 2*x) ( filter (\x -> x>5) n )
As Arthur mentioned, you want something like:
[ if x > 5 then 2*x else x | x <- n ]
It's interpretation is:
Take the next value of n and call it x
Return the value if x > 5 then 2*x else x as then next value of the list.
This is clearer to understand if you don't use list comprehensions and use the map and filter operations instead:
-- Apply a function to every element of the list.
map :: (a -> b) -> [a] -> [b]
-- Throw out list elements that don't pass the test.
filter :: (a -> Bool) -> [a] -> [a]
Your original doubleAll is equivalent this:
-- Multiply every element of the list by two.
doubleAll xs = map (*2) xs
The version where you double only if x > 5 would be this:
-- Apply the `step` function to every element of the list. This step function
-- multiplies by two if x >= 5, otherwise it just returns its argument.
doubleAll xs = map step xs
where step x | x >= 5 = 2*x
| otherwise = x
The problem with the list comprehension version that you wrote is that it's instead equivalent to this:
-- Filter out list elements that are smaller than 5, then double the remaining ones.
doubleAll xs = map (*2) (filter (>=5) xs)
The list comprehension solution that produces the result you want would instead be this:
doubleAll xs = [if x >= 5 then x*2 else x | x <- xs]
As a more general remark, I always recommend to newcomers to stay away from list comprehensions and learn the higher-order list functions, which are more general and less magical.
Disclaimer: I'm new to Haskell and I don't remember a lot about FP from university, so there may be more than one or two errors in my code. This is also my code for Euler Problem 3.
I'm trying to recursively call a function with two arrays as arguments and an array as a result.
The goal:
assume n is 10 for this question
create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
take the first element in 'allFactors' and multiply the rest of the numbers of 'allFactors' by this number. (this generates an array of numbers)
remove all these numbers from 'allNumbers'
continue from 1 to n until 'allFactors' is empty.
Here is my code:
mkList :: Int -> [Int]
mkList n = [1..n-1]
modArray :: Int -> Int -> [Int]
modArray a b = [ x*b | x <- [1..a], x `mod` b == 0]
modArrayAll :: [Int] -> [Int] -> [Int]
modArrayAll [] [] = []
modArrayAll (x:xs) (y:ys) = (e)
where
m = head( ys)
n = length( xs)
e = (modArrayAll xs ys ) \\ modArray n m
(in main)
let allNumbers = mkList (first + 1)
let allFactors = mkList (first + 1)
let mainList2 = modArrayAll allNumbers allFactors
This results in a null list. However, if I have:
e = xs \\ modArray n m --WORKS for one iteration
I get all the odd numbers from 1 to 10.
My Question: Why isn't this working the way I would expect it? I would expect that the recursive stack would hit the empty array condition and just return an empty array which would not be removed from the calling array and it would continue on returning just the prime numbers?
I copied your goal notes:
-- assume n is 10 for this question
n=10
-- create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
allNumbers = [1..n]
-- create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
allFactors = [2..n] -- i suspect you really wanted this rather than [1..n]
-- take the first element in 'allFactors' and
-- multiply the rest of the numbers of 'allFactors' by this number.
-- (this generates an array of numbers)
-- continue from 1 to n until 'allFactors' is empty
factorProducts = [ x*y | x <- allFactors, y <- allFactors]
-- remove all these numbers from 'allNumbers'
whatYouWanted = allNumbers \\ factorProducts
At the moment you seem to still be thinking in a fairly imperative mindset. Try thinking more about what you want, not how to get it :)
modArray n m creates a list of multiples of m, which you then remove from the "main list" of integers. But modArray n m includes 1*m, so each number is removed because it is a "multiple" of itself. In your test case you get only the odd numbers as a result, while you would want 2 to still be in the resulting list. Additionally 1 is included in your list of factors, which will eliminate all numbers, since they are all multiples of 1.
The terminating case of the recursion is modArrayAll [] [] = [], so there an empty list is returned. Then in the surrounding recursive calls this return value is used here:
(modArrayAll xs ys) \\ modArray n m
This tries to remove further elements (those returned by modArray n m) from the already empty list returned by modArrayAll xs ys. No new elements are added anywhere and the result list stays empty. With your algorithm you want the []-case to return the whole list of numbers, not an empty one. Then the \\ modArray n m in the surrounding recursive function calls can filter out more and more of the non-prime factors.