length of list using foldr in haskell - haskell

I wrote the following code to calculate length of a list using foldr in haskell. When I compile the code it gives me error as "myfoldr.hs:3:1: parse error on input `where'". Can anyone please tell me what thing I might be missing or doing wrong in this code ?
mylength :: [Int] -> Int
mylength l = foldr f 0 l
where
f :: Int -> Int -> Int
f x y = y+1

In Haskell, whitespace matters - look at the guide on the Haskell wiki.
Formatting your code more correctly gives:
mylength :: [Int] -> Int
mylength l = foldr f 0 l
where
f :: Int -> Int -> Int
f x y = y + 1
Which works perfectly (although the argument x to f is a bit redundant, you might want to write it as f _ y = y + 1 instead, or use a lambda expression like foldr (\_ x -> x + 1) 0 l).

This is an indentation error: you have to indent the where clause, since otherwise Haskell will see the definition of f as a separate function. So we can fix it with:
mylength :: [Int] -> Int
mylength l = foldr f 0 l
where f :: Int -> Int -> Int
f x y = y+1
Nevertheless we can still make it more generic: instead of defining it for an [Int] list, we can define it over an [a] list, with:
mylength :: [a] -> Int
mylength l = foldr f 0 l
where f x y = y+1
We can also rewrite f as const (+1), so:
mylength :: Num n => [a] -> n
mylength = foldr (const (1+)) 0
Note that we can apply an eta-reduction here: remove l both in the head and the body of the mylength definition. Or in case we know that the number is also enumerable, we can use succ instead of (1+):
mylength :: (Enum n, Num n) => [a] -> n
mylength = foldr (const succ) 0

Related

Haskell: for every even appearance in an array, concatenate an int to the final list

I'm currently trying to write a function that takes as arguments an Int and an array of Ints and for every even value in the array, it concatenates the Int to the final array.
So, something like this:
f 3 [1,2,3,4,5,6] = [1,2,3,3,4,3,5,6,3]
This is the code I imagined would work (I'm just beginning so sorry if it's bad):
f :: Int -> [Int] -> [Int]
f(x,[]) = []
f(x,y)
|even head(y) = (head(y) ++ [x] ++ f(x,drop 1 y)
|otherwise = head(y) ++ f(x,(drop 1 y))
The error I'm getting is "Couldn't match expected type of 'Int' with actual type (a3, [[a3]])'. I understand the parameters types are mismatched, but I'm not sure how a proper syntax would look like here
You use (x, []), so that means the input type would be a tuple, so f :: (Int, [Int]) -> [Int].
I would also use pattern matching instead of head and tail, so:
f :: Int -> [Int] -> [Int]
f _ [] = []
f x (y:ys)
| even y = y : x : f x ys
| otherwise = y : f x ys
You can also generalize the type signature, and work with an inner function to avoid passing the x each time:
f :: Integral a => a -> [a] -> [a]
f x = go
where go [] = []
go (y:ys)
| even y = y : x : go ys
| otherwise = y : go ys
Another way of looking at this would be using a right fold to insert the desired element after even numbers.
f :: Int -> [Int] -> [Int]
f x lst = foldr (\y i -> if even y then y:x:i else y:i) [] lst
Which we can simplify to:
f :: Int -> [Int] -> [Int]
f x = foldr (\y i -> if even y then y:x:i else y:i) []
Note that without specifying the type, the more general inferred type of f would be:
f :: (Foldable t, Integral a) => a -> t a -> [a]

How is map implemented internally?

Ok so i want to implement my custom map that receives a replication factor and a target list.
Inputs: Int -> [Int]
Output: [[Int]]
E.g.: 2 [1,2] -----> [[1,1],[2,2]]
f [1,2,3] -> map -> [f(1),f(2),f(3)]
What is supposed to happen with f(1) when map goes to the next element of the list?How should i replace 1 with f(1) ?
P.S: This was my initial solution but it does replicate the initial list,not every element.
replicate::Int->[Int]->[[Int]]
replicate 1 x=x
replicate factor (x:xs)= go factor [] (x:xs) where
go factor ls (x:xs) =go factor (repl factor x):ls xs
repl 1 nr=nr
repl times nr=nr:repl (times-1) nr
There are two issues, that prevent your code from compiling:
null function has the type [a0] -> Bool, but you're applying it
on an element of a list, hence you're expecting it to be Int -> Bool
The result f x shouldn't be pushed into the tail of the input, it
should be pushed into the result of recursive call of the function:
f x: (mymap f xs) instead of f x: xs
As a result the following code should work:
mymap :: (Int -> [Int]) -> [Int]-> [[Int]]
mymap f (x:xs) = if null xs then [] else f x : (mymap f xs)
By the way, the Standard Library provides much readable (and also polymorphic) implementation using pattern-matching:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
custom map that receives a replication factor and a target list
It is a little unclear to me what you're asking for.
Does mymap receive the replication factor, or does f?
E.g.: 2 [1,2] -----> [[1,1],[2,2]]
If you want mymap 2 [1,2] to give [[1,1],[2,2]], then:
mymap :: Int -> [a] -> [[a]]
mymap = map . replicate
However,
mymap :: (Int -> [Int]) -> [Int] -> [[Int]]
How is this function any different from the built-in map :: (a -> b) -> [a] -> [b] with a as Int and b as [Int]? Here, mymap does not have any Int argument itself, so you must mean that f's argument is the replication factor; but if f 2 3 == [3,3], then f is replicate and you can use the solution above.
You can write this using your own recursive definitions, if you like:
mymap :: Int -> [a] -> [[a]]
mymap _ [] = []
mymap n (x:xs) = myreplicate n x : mymap n xs
myreplicate :: Int -> a -> [a]
myreplicate 0 _ = []
myreplicate n x = x : myreplicate (n-1) x
Or you can use list comprehension instead of a map:
mymap :: Int -> [a] -> [[a]]
mymap n xs = [ replicate n x | x <- xs ]
I'd probably call mymap for replicateMany or something like that.

How do I put a element n times in a list without using the replicate or repeat function?

I have a function rep which requires a list with ints. My task now is to put each of these numbers in separate lists with n times the number. For example
[1,3,5] to [[1],[3,3,3],[5,5,5,5,5]] So far I can put each int in a separate list but I don't really now how to put them n times in the list without using replicate or repeat.
This is the code I have so far:
rep [] = []
rep (x1:xs) = [[x1]] ++ (rep xs)
As this is a homework/learning exercise - just want to give some hints
Split the task in two parts a function
myReplicate :: Int -> a -> [a] which replicates a single element as many times as the Int tells it to.
myReplicate n x | n > 0 = ...
| n == 0 = ...
| n < 0 = error "Error myReplicate: no negative arguments allowed"
a second function myMap :: (a -> b) -> [a] -> [b] that applies a function to every element of a given list.
myMap :: (a -> b) -> [a] -> [b]
myMap f [] = []
myMap f (x:xs) = ...
then rep = myMap (\x -> myReplicate x x)
Here a solution without repeat or replicate:
rep = map (\ n -> foldr (const (n :)) [] [1..n])

No instance for (Num a) arising from a use of `sum' - Instance Num

this function works fine:
fromDigits :: [Int] -> Int
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: [Int] -> Int -> [Int]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
But if i want to change the type signature from the function, it does not work:
fromDigits :: (Num a) => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: (Num a) => [a] -> a -> [a]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
Shouldn't this work too?
Almost, but not quite. The basic problem is that length has type [a]->Int. This will work:
fromDigits :: Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: Num b => [b] -> Int -> [b]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
As Oleg Grenrus points out, one should always be careful to check if Int might overflow. It is in fact possible for this to happen if Int is 30, 31, or 32 bits, although it is relatively unlikely. However, if that is a concern, there is a way around it, using another function:
lengthIsExactly :: Integral n => n -> [a] -> Bool
lengthIsExactly = -- I'll let you figure this one out.
-- Remember: you can't use `length` here,
-- and `genericLength` is horribly inefficient,
-- and there's a completely different way.
You can make it easier to see how the types of fromDigits and f match up using a GHC extension. Enable the extension by adding
{-# LANGUAGE ScopedTypeVariables #-}
to the very top of your source file. Then you can write
fromDigits :: forall a . Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: [a] -> Int -> [a]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
This way, it's clear that the list arguments all have the same type.
The problem is that you are using other functions that require even more of type a than just Num a
(^) requires "Integral a"
This works
fromDigits' :: (Num a, Integral a)=>[a] -> a
fromDigits' n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: (Num a, Integral a)=>[a] -> a -> [a]
f n x = if (x==fromIntegral (length n)) then []
else (10^x):f n (x+1)

Can mapEvery be implemented with foldr

For a function that maps a function to every nth element in a list:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f = zipWith ($) (drop 1 . cycle . take n $ f : repeat id)
Is it possible to implement this with foldr like ordinary map?
EDIT: In the title, changed 'folder' to 'foldr'. Autocorrect...
Here's one solution
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f as = foldr go (const []) as 1 where
go a as m
| m == n = f a : as 1
| otherwise = a : as (m+1)
This uses the "foldl as foldr" trick to pass state from the left to the right along the list as you fold. Essentially, if we read the type of foldr as (a -> r -> r) -> r -> [a] -> r then we instantiate r as Int -> [a] where the passed integer is the current number of elements we've passed without calling the function.
Yes, it can:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f xs
= foldr (\y ys -> g y : ys) []
$ zip [1..] xs
where
g (i, y) = if i `mod` n == 0 then f y else y
And since it's possible to implement zip in terms of foldr, you could get even more fold-y if you really wanted. This even works on infinite lists:
> take 20 $ mapEvery 5 (+1) $ repeat 1
[1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2]
This is what it looks like with even more foldr and inlining g:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery _ _ [] = []
mapEvery n f xs
= foldr (\(i, y) ys -> (if i `mod` n == 0 then f y else y) : ys) []
$ foldr step (const []) [1..] xs
where
step _ _ [] = []
step x zipsfn (y:ys) = (x, y) : zipsfn ys
Now, would I recommend writing it this way? Absolutely not. This is about as obfuscated as you can get while still writing "readable" code. But it does demonstrate that this is possible to use the very powerful foldr to implement relatively complex functions.

Resources