Re-write 'map intToDigit' with a fold... - haskell

So this one seems like it should be super-simple... but I'm not sure where to stick the 'fold' in (obviously you could fold either way)...
It says "write a function ( intToString :: [Int] -> [Char] ) using a fold, that mimics this map:
map intToDigit [5,2,8,3,4] == "52834"
And then says, "For the conversion, use intToDigit :: Int -> Char from Data.Char."
I'm not entirely sure I get the point... but yet it doesn't seem like it should be that hard -- you're just reading in the list (folding it in, I get how folds work in general) from either the left or right and doing the conversion... but I'm not sure how to set it up.

It is not difficult, think about the definition foldr (or foldl) of List:
foldr::(a -> b -> b) -> b -> [a] -> b
Here (a->b->b) is the step function which will be applied on each element of list [a], b is your target.
Now, you have a list of Int ([Int]), and need to convert to [Char] (or String).
Relpace [a] by [5,2,8,3,4], b by []::[Char] (your target) and (a->b->b) by step function :
foldr step ([]::[Char]) [5,2,8,3,4]
We have known that step function has type (a->b->b), specifically, (Int->[Char]->[Char]), the job need to do just convert Int to [Char], as mentioned in question: intToDigit can be helped to convert Int to Char and (:) operator can append element at the head of List so:
step x s = intToDigit x : s
where s is [Char] (or String), put them all:
foldr (\x s->intToDigit x : s) [] [5,2,8,3,4]

Related

Insufficient definition of replicate

I have a question that I think is rather tricky.
The standard prelude contains the function
replicate :: Int -> a -> [a]
The following might seem like a reasonable definition for it
replicate n x = take n [x,x,..]
But it is actually not sufficient. Why not?
I know that the replicate function is defined as:
replicate :: Int -> a -> [a]
replicate n x = take n (repeat x)
And repeat is defined as:
repeat :: a -> [a]
repeat x = xs where xs = x:xs
Is the definition insufficient (from the question) because it uses an infinite list?
First of all there is a small syntax error in the question, it should be:
replicate n x = take n [x,x..]
-- ^ no comma
but let's not be picky.
Now when you use range syntax (i.e. x..), then x should be of a type that is an instance of Enum. Indeed:
Prelude> :t \n x -> take n [x,x..]
\n x -> take n [x,x..] :: Enum a => Int -> a -> [a]
You can argue that x,x.. will only generate x, but the Haskell compiler does not know that at compile time.
So the type in replicate (in the question) is too specific: it implies a type constraint - Enum a - that is actually not necessary.
Your own definition on the other hand is perfectly fine. Haskell has no problem with infinite lists since it uses lazy evaluation. Furthermore because you define xs with xs as tail, you actually constructed a circular linked list which also is better in terms of memory usage.

Couldn't match expected type error

As a beginner, I was working on item number 3 of the Haskell 99 problems. The first code snippet is my solution. However, I cannot add the type declaration of [a] -> Int -> a.
It produces an error: Couldn't match type 'a' with 'Int'
--My Solution
--elementAt :: [a] -> Int -> a
elementAt xs num = head . reverse $ takeWhile (<num+1) xs
Meanwhile, one of the solution in the problem 3 works perfectly with the same output.
elementAt' :: [a] -> Int -> a
elementAt' list i = list !! (i - 1)
I've used the :type in the GHCI for the elementAt without the declaration and it shows:
elementAt :: (Num c, Ord c) => [c] -> c -> c
What is the difference of the two functions?
takeWhile (<num+1) xs says that you want to take elements at the front of the list xs while the element (not the index!) is less than num + 1. Since you're comparing num (which is an Int) with the list elements, the compiler infers that the list elements have to be Int as well, which contradicts your type declaration.
Without the type declaration, GHC infers that xs's elements and num have to be the same type (since you compare list elements with num). This type has to have an Ord instance (for the comparison) as well as a Num instance (because of the addition).
The type of takeWhile (< num + 1) is [Int] -> [Int].
However the type of xs is [a].
Essentially you are trying to apply a predicate Int -> Bool to elements of type a.
If you want to filter based on the position in the list, you first need to augment the input list with the position of each element. You can do this fairly easily with zip:
zip xs [1..]
You can then drop elements based on the value of the second element of the resulting list.

What are the alternatives to prelude's iterate if the "output" values are not the same as those being iterated on?

I have come across a pattern where, I start with a seed value x and at each step generate a new seed value and a value to be output. My desired final result is a list of the output values. This can be represented by the following function:
my_iter :: (a -> (a, b)) -> a -> [b]
my_iter f x = y : my_iter f x'
where (x',y) = f x
And a contrived example of using this would be generating the Fibonacci numbers:
fibs:: [Integer]
fibs = my_iter (\(a,b) -> let c = a+b in ((b, c), c)) (0,1)
-- [1, 2, 3, 5, 8...
My problem is that I have this feeling that there is very likely a more idiomatic way to do this kind of stuff. What are the idiomatic alternatives to my function?
The only ones I can think of right now involve iterate from the Prelude, but they have some shortcomings.
One way is to iterate first and map after
my_iter f x = map f2 $ iterate f1 x
where f1 = fst . f
f2 = snd . f
However, this can look ugly if there is no natural way to split f into the separate f1 and f2 functions. (In the contrived Fibonacci case this is easy to do, but there are some situations where the generated value is not an "independent" function of the seed so its not so simple to split things)
The other way is to tuple the "output" values together with the seeds, and use a separate step to separate them (kind of like the "Schwartzian transform" for sorting things):
my_iter f x = map snd . tail $ iterate (f.fst) (x, undefined)
But this seems wierd, since we have to remember to ignore the generated values in order to get to the seed (the (f.fst) bit) and add we need an "undefined" value for the first, dummy generated value.
As already noted, the function you want is unfoldr. As the name suggests, it's the opposite of foldr, but it might be instructive to see exactly why that's true. Here's the type of foldr:
(a -> b -> b) -> b -> [a] -> b
The first two arguments are ways of obtaining something of type b, and correspond to the two data constructors for lists:
[] :: [a]
(:) :: a -> [a] -> [a]
...where each occurrence of [a] is replaced by b. Noting that the [] case produces a b with no input, we can consolidate the two as a function taking Maybe (a, b) as input.
(Maybe (a, b) -> b) -> ([a] -> b)
The extra parentheses show that this is essentially a function that turns one kind of transformation into another.
Now, simply reverse the direction of both transformations:
(b -> Maybe (a, b)) -> (b -> [a])
The result is exactly the type of unfoldr.
The underlying idea this demonstrates can be applied similarly to other recursive data types, as well.
The standard function you're looking for is called unfoldr.
Hoogle is a very useful tool in this case, since it doesn't only support searching functions by name, but also by type.
In your case, you came up with the desired type (a -> (a, b)) -> a -> [b]. Entering it yields no results - hmm.
Well, maybe there's a standard function with a slightly different syntax. For example, the standard function might have its arguments flipped; let's look for something with (a -> (a, b)) in its type signature somewhere. This time we're lucky as there are plenty of results, but all of them are in exotic packages and none of them seems very helpful.
Maybe the second part of your function is a better match, you want to generate a list out of some initial element after all - so type in a -> [b] and hit search. First result: unfoldr - bingo!
Another possibility is iterateM in State monad:
iterateM :: Monad m => m a -> m [a]
iterateM = sequence . repeat
It is not in standard library but it's easy to build.
So your my_iter is
evalState . sequence . repeat :: State s a -> s -> [a]

Haskell Map function implementation issues

I just began to learn Haskell and am having trouble with adjusting to the language, for example on the implementation of map more specifically when trying to do similar operations as in the example bellow;
rotate :: Dimensions -> imgBlock -> [(imgBlock,Int)]
rotate d ((p, pix), s, t)
= zip [((p, f pix), s, t) | f <- transformate (fst d)] [0..7]
makeAllRotations :: Dimensions -> [imgBlock] -> [(imgBlock,Int)]
makeAllRotations d ib = map concat (rotate d ib) //Error points Here
Where
type imgBlock = (Block, Int, Int)
type Block = (Pnt, Pxl)
type Dimensions = (Int, Int)
And this is one of the errors i get
asdf.hs:73:30:
Couldn't match expected type `(imgBlock, Int)'
with actual type `[a0]'
Expected type: [[a0]] -> (imgBlock, Int)
Actual type: [[a0]] -> [a0]
In the first argument of `map', namely `concat'
In the expression: map concat (rotate d ib)
I find myself quite frustrated trying to adjust to this new programming 'paradigm' where most of the things I managed to do are through trial and error. I am obviously not understanding map correctly, although i have read the documentation on this website, but all the examples are shown in console like map (2+) [1,2,3] not so much when using them in functions.
Could I get some pointers on where am i going wrong on my map implementation. Thks
The best way to find the problem is to look at the types:
rotate :: Dimensions -> ImgBlock -> [(ImgBlock,Int)]
makeAllRotations :: Dimensions -> [ImgBlock] -> [(ImgBlock,Int)]
map :: (a -> b) -> [a] -> [b]
concat :: [[a]] -> [a]
The map function is trying to call concat on each of the (ImgBlock,Int) pairs in the list returned by rotate. But concat expects to get a nested list as its argument. But the big thing that helped me figure out how to fix it was looking at rotate d ib. The second argument to rotate is ImgBlock, but in that context ib :: [ImgBlock]. You can't pass in a list when a single item is expected. But that's what the map function is for. It allows you to take a function that accepts a single item ('a' in the type signature above) and use that function when you have [a]. I suspect what you want is something like this:
makeAllRotations d ib = concat $ map (rotate d) ib
Because rotate returns a list, map (rotate d) ib returns a list of lists, which fits perfectly as the first argument to the concat function.

Haskell recursive map function

Why does this throw an error?
myTest :: Int -> [Int]
myTest a
| a == 0 = []
| otherwise = x ++ map(myTest) x
where x = [a-1]
I would expect that it would make a list going from a to 1. Instead I get the error:
couldn't match the expected type 'Int' against inferred type '[Int]'
in the first argument of 'map', namely '(myTest)'
in the second argument of '(++)', namely 'map (myTest) x'
This obviously isn't the best way to make this list, but it is a simplified version of a more complicated problem I am having.
I basically have a function foo :: a -> [a], and in the resulting list I need to call foo on every element expanding it into another list. In the end I want one big list where every element is a base case.
I am fairly new at Haskell so I am probably missing something fairly basic.
The signature of myTest is Int -> [Int].
The signature of map is (a -> b) -> [a] -> [b], and since myTest is the first argument, that makes it (Int -> [Int]) -> [Int] -> [[Int]].
But your function expects it to produce an [Int], not an [[Int]].
Edit to add: I think what you want is simply
myTest a
| a == 0 = []
| otherwise = [a] ++ myTest (a-1)
although this is probably not what you should want (it's much more heavyweight than an idiomatic Haskell solution), but without seeing your actual problem that this is a simplification of, it's hard to tell.
myTest :: Int -> [Int]
myTest 0 = []
myTest a = a : myTest (a-1)
Else's answer is better because is uses (:) instead of (++). In your case you can use either, because (:) adds a single element to the front of the list, and that's what you're trying to do.
(++) is a relatively expensive operation because it copies the spine of the left hand list. (:) is cheap because it never copies anything, it just creates a new cons cell that contains your new head element.
So always use (:) instead of (++) if you can.
EDIT: Just trying to explain since Else didn't post an explanation for his code.

Resources