Why are these functions differently evaluated - haskell

I was experimenting with haskell, and while trying to improve the readability of my code I suddenly changed the behaviour of it. I would have thought these two variants would be equivalent.
Original:
f :: Eq c => c -> c -> [[c]] -> [[c]]
f d c acc
| c == d = [] : acc
| otherwise = ([c] ++ (head acc)) : tail acc
split :: Eq a => a -> [a] -> [[a]]
split delim = foldr (f delim) [[]]
Here is the second one:
f' :: Eq c => c -> c -> [[c]] -> [[c]]
f' d c (currentWord:wordsSoFar)
| c == d = [] : currentWord : wordsSoFar
| otherwise = (c : currentWord) : wordsSoFar
split' :: Eq a => a -> [a] -> [[a]]
split' delim = foldr (f' delim) [[]]
Here are the results of running the two:
*Main> take 1 (split 5 [1..])
[[1,2,3,4]]
*Main> take 1 (split' 5 [1..])
*** Exception: stack overflow

Your first version only needs to evaluate acc when you call head and tail on it, so no evaluation takes place when c == d.
The second version needs to know whether acc is empty or not before it does anything else as none of the other code must execute if the pattern does not match. This means that acc has to be evaluated even if c == d. This leads to an infinite loop.
You can make the second version work by using an irrefutable pattern like this:
f' d c ~(currentWord:wordsSoFar) =
By making the pattern irrefutable, you're saying that you know that the pattern will match, so no check is necessary. If acc were empty, this would cause an error to happen when (and if) you used currentWord and wordsSoFar instead of a non-exhaustive pattern error happening right away (and regardless of whether currentWord and wordsSoFar are actually used).

I think this should be equivalent:
f d c acc | c == d = [] : acc
f d c (currentWord:wordsSoFar) = (c : currentWord) : wordsSoFar
Notice that if c == d then we don't attempt to determine whether acc is empty or not. (All versions of your code will actually fail if c == d and acc == []; I presume this never happens.)

Related

higher order function haskell

I'm new to Haskell, I've to do a function that counts the number of vowels in a string using the higher order function foldr
I've tried to create this function
vowels [] = 0
vowels (x:xs)= if elem x "aeiou" then 1 + vowels xs else vowels xs
But it doesn't work and I'm not able to do it using foldr, any suggestion?
Well a foldr :: (a -> b -> b) -> b -> [a] -> b is a function where the first parameter is a function f :: a -> b -> b. You can here see the a parameter as the "head" of the list, the second parameter b as the result of the recursion with foldr, and you thus want to produce a result in terms of these two for the entire function. This logic is basically encapsulated in the second clause of your function.
Indeed:
vowels (x:xs) = if elem x "aeiou" then 1 + vowels xs else vowels xs
can be rewritten as:
vowels (x:xs) = if elem x "aeiou" then 1 + rec else rec
where rec = vowels xs
and rec is thus the outcome of the recursive call, the second parameter of the "fold"-function. x on the other hand is the first parameter of the "fold"-function. We thus need to write this function, only in terms of x and rec, and this is simply:
\x rec -> if elem x "aeiou" then 1 + rec else rec
Furthermore we need to handle the case of an empty list, this is the first clause of your function. In that case the result is 0, this is the second paramter of the foldr, so we got:
vowels = foldr (\x rec -> if elem x "aeiou" then 1 + rec else rec) 0
Or a more clean syntax:
vowels = foldr f 0
where f x rec | elem x "aeiou" = 1 + rec
| otherwise = rec
We can further clean it up, by abstracting away rec:
vowels = foldr f 0
where f x | elem x "aeiou" = (1+)
| otherwise = id
You need to take a look at foldr's signature.
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Never mind the Foldable part and focus on the first function it takes.
(a -> b -> b) b is the same type that you are supposed to return, so directly translating the signature into a lambda gives you \x acc -> acc, but you want to do more than just ignore every element.
Take a look at your function if elem x "aeiou" then 1 + vowels xs else vowels xs. You need to return b, not recurse adding one to it.
if elem x "aeiou" this part is fine. then 1 + acc <- see what I'm doing here? I'm adding one to the accumulator, not recursing manually, that is done by foldr, as for the else case: acc. That's it. You don't need to even touch x.
Putting it all together: vowels = foldr (\x acc -> if elem x "aeiou" then 1 + acc else acc) 0
The 0 is what the acc will start as.
If you want to know more about folds, I suggest you reimplement them yourself.
The easiest way to write something like that is to let the compiler guide you.
First, look only at the obvious parts of the foldr signature. This is the traditional signature, specialised to lists. Nowedays, foldr can actually work on any other suitable container as well, but this isn't important here.
foldr :: (a -> b -> b) -- ^ Not obvious
-> b -- ^ Not obvious
-> [a] -- ^ A list... that'll be the input string
-> b -- ^ Final result, so nothing to be done here.
So, your implementation will be of the form
vowels :: String -> Int
vowels s = foldr _ _ s
where we yet need to find out what to put in the _ gaps. The compiler will give you useful hints as to this:
$ ghc wtmpf-file6869.hs
[1 of 1] Compiling Main ( wtmpf-file6869.hs, wtmpf-file6869.o )
/tmp/wtmpf-file6869.hs:2:18: error:
• Found hole: _ :: Char -> Int -> Int
• In the first argument of ‘foldr’, namely ‘_’
In the expression: foldr _ _ s
In an equation for ‘Main.vowels’: Main.vowels s = foldr _ _ s
• Relevant bindings include
s :: String (bound at /tmp/wtmpf-file6869.hs:2:8)
vowels :: String -> Int (bound at /tmp/wtmpf-file6869.hs:2:1)
|
2 | vowels s = foldr _ _ s
| ^
So, a function that merely takes a single character, and then modifies an integer. That was actually already part of your original implementation:
vowels (x:xs) = if elem x "aeiou" then 1 + vowels xs else vowels xs
The bold part is essentially a function of a single character, that yields a number-modifier. So we can put that in the foldr implementation, using lambda syntax:
vowels s = foldr (\x -> if x`elem`"aeiou" then (1+) else _) _ s
I had to put the 1+ in parenthesis so it works without an explicit argument, as an operator section.
Ok, more gaps:
• Found hole: _ :: Int -> Int
• In the expression: _
In the expression: if x `elem` "aeiou" then (1 +) else _
In the first argument of ‘foldr’, namely
‘(\ x -> if x `elem` "aeiou" then (1 +) else _)’
• Relevant bindings include
x :: Char (bound at wtmpf-file6869.hs:2:20)
s :: String (bound at wtmpf-file6869.hs:2:8)
vowels :: String -> Int (bound at wtmpf-file6869.hs:2:1)
|
2 | vowels s = foldr (\x -> if x`elem`"aeiou" then (1+) else _) _ s
| ^
So that's the modifier that should take action when you've found a non-vowel. What do you want to modify in this case? Well, nothing actually: the count should stay as-is. That's accomplished by the id function.
vowels s = foldr (\x -> if x`elem`"aeiou" then (1+) else id) _ s
• Found hole: _ :: Int
• In the second argument of ‘foldr’, namely ‘_’
In the expression:
foldr (\ x -> if x `elem` "aeiou" then (1 +) else id) _ s
In an equation for ‘vowels’:
vowels s
= foldr (\ x -> if x `elem` "aeiou" then (1 +) else id) _ s
• Relevant bindings include
s :: String (bound at wtmpf-file6869.hs:2:8)
vowels :: String -> Int (bound at wtmpf-file6869.hs:2:1)
|
2 | vowels s = foldr (\x -> if x`elem`"aeiou" then (1+) else id) _ s
| ^
So that's an integer that's completely outside of the foldr. I.e. it can't depend on the string. In particular, it will also be used if the string is empty. Can only be 0!
vowels s = foldr (\x -> if x`elem`"aeiou" then (1+) else id) 0 s
No more gaps, so the compiler will just accept this. Test it:
$ ghci wtmpf-file6869
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/sagemuej/.ghc/ghci.conf
Loaded GHCi configuration from /home/sagemuej/.ghci
[1 of 1] Compiling Main ( wtmpf-file6869.hs, interpreted )
Ok, 1 module loaded.
*Main> vowels "uwkaefdohinurheoi"
9
Your definition can be tweaked into
vowels [] = 0
vowels (x:xs) = g x (vowels xs)
where
g x rec = if elem x "aeiou" then 1 + rec else rec
which matches the pattern
foldr r z [] = z
foldr r z (x:xs) = r x (foldr r z xs)
if we have foldr r z = vowels and r = g, and also z = 0.
That "pattern" is in fact a valid definition of the foldr function.
Thus we indeed have
vowels xs = foldr g 0 xs
where
g x rec = if elem x "aeiou" then 1 + rec else rec

Haskell type mismatch Int and [Int]

I'm a beginner to Haskell. I'm trying to create a function which has two parameters: a character and a string.
This function is supposed to go through the string and check if the character given is in the string, and then return a list of integers representing the position of the characters in the string.
My code is:
tegnPose :: Char -> String -> [Int]
tegnPose c [] = []
tegnPose c (x:xs) = [if not (xs !! a == c)
then [a] ++ tegnPose c xs
else tegnPose c xs |a <- [0.. length xs - 1]]
Which is a recursive function with list comprehension.
The error I get:
Uke4.hs:14:7: error:
* Couldn't match expected type `Int' with actual type `[Int]'
* In the expression: [a] ++ tegnPose c xs
In the expression:
if not (xs !! a == c) then [a] ++ tegnPose c xs else tegnPose c xs
In the expression:
[if not (xs !! a == c) then
[a] ++ tegnPose c xs
else
tegnPose c xs |
a <- [0 .. length xs - 1]]
|
14 | then [a] ++ tegnPose c xs
| ^^^^^^^^^^^^^^^^^^^^
Uke4.hs:15:7: error:
* Couldn't match expected type `Int' with actual type `[Int]'
* In the expression: tegnPose c xs
In the expression:
if not (xs !! a == c) then [a] ++ tegnPose c xs else tegnPose c xs
In the expression:
[if not (xs !! a == c) then
[a] ++ tegnPose c xs
else
tegnPose c xs |
a <- [0 .. length xs - 1]]
|
15 | else tegnPose c xs |a <- [0.. length xs - 1]]
I don't understand how the mismatch happens, as the recursive function should just run through.
Here's why the mismatch happens. First, note that a list comprehension that returns a list of type [a] must generate elements of type a, so you need the following to match:
example :: [Int]
-- .-- the final value is "[Int]"
-- |
example = [ 2+x*y | x <- [1..10], y <- [1..5], x < y]
-- ^^^^^
-- |
-- `- therefore, this must be "Int"
In your example, the type signature for tegnPose implies that the list comprehension must return an [Int], but the expression generating list elements, namely:
if ... then [a] ++ tegnPose c xs else tegnPose c cx
is clearly not returning a plain Int the way it's supposed to.
The first error message is indicating that actual type of the subexpression [a] ++ tegnPos c xs which is [Int] does not match the expected type of the result of the entire if .. then .. else expression which should have type Int.
If I understand your question correctly (i.e., return a list of the integer positions of each occurrence of a character in a string so that tegnPose 'a' "abracadabra" returns [0,3,5,7,10], then you should either use recursion or a list comprehension, but not both.
Note that the non-recursive list comprehension:
tegnPose c xs = [a | a <- [0..length xs - 1]
almost does what you want. All that's missing is testing the condition to see if the character at position a is a c. If you don't know about using "guards" in list comprehensions, go look it up.
Alternatively, the recursive function without a list comprehension:
tegnPose c (x:xs) = if (x == c) then ??? : tegnPose c xs
else tegnPose c xs
tegnPose _ [] = []
also almost does what you want, except it's not obvious what to put in place of ??? to return a number indicating the current position. If you write a recursive version with an extra parameter:
tp n c (x:xs) = if (x == c) then n : tp (???) c xs
else tp (???) c xs
tp _ _ [] = []
with the idea that you could define:
tegnPose c xs = tp 0 c xs
then you'd be closer, if only you could figure out what new value for n should go in place of the ???.
More standard Haskell solutions might involve things like zips:
> zip [0..] "abracadabra"
[(0,'a'),(1,'b'),(2,'r'),...]
and filters:
> filter (\(i,c) -> c == 'a') $ zip [0..] "abracadabra"
[(0,'a'),(3,'a'),...]
and maps:
> map fst $ filter (\(i,c) -> c == 'a') $ zip [0..] "abracadabra"
[0,3,5,7,10]
or looking in Data.List for a function that does what you want:
> elemIndices 'a' "abracadabra"
[0,3,5,7,10]
Just for some variety a simpler way of implementing this functionality with a single foldr could be;
import Data.Bool (bool)
charIndices :: Char -> String -> [Int]
charIndices c = foldr (\t r -> bool r (fst t : r) (snd t == c)) [] . zip [0..]
*Main> charIndices 't' "tektronix test and measurement instruments"
[0,3,10,13,29,34,40]
Explanation:
Type of foldr is Foldable t => (a -> b -> b) -> b -> t a -> b
It takes three parameters;
A function which accepts two parameters
An initial value of type b
A traversable data type which hold values of type a
an returns a single value of type b.
In this particular case our type a value is Char type, which makes t a a String type (due to type signature) and type b value is a list of integers [Int].
The provided function as the first parameter is (\t r -> bool r (fst t : r) (snd t == c)) which is very simple if you check Data.bool. bool is a ternary operator of type a -> a -> Bool -> a which takes three arguments. In order they are negative result, positive result and condition. (negative is on the left as usual in Haskell). It checks if the current character is equal to our target character c, if so it returns fst t : r if not r (r means result). And finally t is the current tuple of the fed tuples list. The tuples list is constructed by zip [0..] s where s is not shown in the function definition due to partial application.

Get positions of elements in list of strings in Haskell

my title might be a bit off and i'll try to explain a bit better what i'm trying to achieve.
Basically let's say i have a list:
["1234x4","253x4",2839",2845"]
Now i'd like to add all the positions of the strings which contain element 5 to a new list. On a current example the result list would be:
[1,3]
For that i've done similar function for elem:
myElem [] _ = False
myElem [x] number =
if (firstCheck x) then if digitToInt(x) == number then True else False else False
myElem (x:xs) number =
if (firstCheck x) then (if digitToInt(x) == number then True else myElem xs number) else myElem xs number
where firstCheck x checks that the checked element isn't 'x' or '#'
Now in my current function i get the first element position which contains the element, however my head is stuck around on how to get the full list:
findBlock (x:xs) number arv =
if myElem x number then arv else findBlock xs number arv+1
Where arv is 0 and number is the number i'm looking for.
For example on input:
findBlock ["1234x4","253x4",2839",2845"] 5 0
The result would be 1
Any help would be appreciated.
The function you want already exists in the Data.List module, by the name of findIndices. You can simply use (elem '5') as the predicate.
http://hackage.haskell.org/package/base-4.8.1.0/docs/Data-List.html#v:findIndices
If, for some reason, you're not allowed to use the built-in one, it comes with a very pretty definition (although the one actually used has a more complicated, more efficient one):
findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]
By the way, I found this function by searching Hoogle for the type [a] -> (a -> Bool) -> [Int], which (modulo parameter ordering) is obviously the type such a function must have. The best way to find out of Haskell has something is to think about the type it would need to have and search Hoogle or Hayoo for the type. Hoogle is better IMO because it does slightly fuzzy matching on the type; e.g. Hayoo wouldn't find the function here by the type I've given, because it take the arguments in the reverse order.
An implementation of findIndices, for instructional purposes:
findIndices ok list = f list 0 where
f [] _ = []
f (x:xs) ix
| ok x = ix : f xs (ix+1)
| otherwise = f xs (ix+1)
Use it like findIndices (elem '5') my_list_o_strings
You're trying to work your way through a list, keeping track of where you are in the list. The simplest function for doing this is
mapWithIndex :: (Int -> a -> b) -> [a] -> [b]
mapWithIndex = mwi 0 where
mwi i _f [] = i `seq` []
mwi i f (x:xs) = i `seq` f i x : mwi (i+1) f xs
This takes a function and a list, and applies the function to each index and element. So
mapWithIndex (\i x -> (i, x)) ['a', 'b', 'c'] =
[(0,'a'), (1,'b'),(2,'c')]
Once you've done that, you can filter the list to get just the pairs you want:
filter (elem '5' . snd)
and then map fst over it to get the list of indices.
A more integrated approach is to use foldrWithIndex.
foldrWithIndex :: (Int -> a -> b -> b) -> b -> [a] -> b
foldrWithIndex = fis 0 where
fis i _c n [] = i `seq` n
fis i c n (x:xs) = i `seq` c i x (fis (i+1) c n xs)
This lets you do everything in one step.
It turns out that you can implement foldrWithIndex using foldr pretty neatly, which makes it available for any Foldable container:
foldrWithIndex :: (Foldable f, Integral i) =>
(i -> a -> b -> b) -> b -> f a -> b
foldrWithIndex c n xs = foldr go (`seq` n) xs 0 where
go x r i = i `seq` c i x (r (i + 1))
Anyway,
findIndices p = foldrWithIndex go [] where
go i x r | p x = i : r
| otherwise = r

Incorrect where indentation? Short code

I tried to make a very short code, because we have a reglementation that favors the shortest code.
We have to create a function that turns a list into a new list of ascending and descending lists in the same order: For example. [1,6,2,1,7,3,2,8,4], becomes [[1,6],[2,1],[7],[3,2],[8],[4]]
So i tried to do the following:
func :: Ord a => [a] -> [[a]]
func xs = f1 d [a]
f1 [] ys = [c]
f1 xs ys | a >= b = d `f1` a:ys
| otherwise = c: d `f2` [a]
f2 [] ys = [c]
f2 xs ys | a < b = d `f2` a:ys
| otherwise = c : d `f1` [a]
where a = head xs
b = head ys
c = reverse ys
d = tail xs
But i get
parse error on input '='
on the line "b = head ys".
I thought it is possible to define multiple functions in the where block?
Other indentations created errors like a lot of
not in scope 'a'
not in scope 'b'
not in scope 'c'
not in scope 'd'
or
parse error on input 'b'
I have to make it that way to save some tokens/ have shorter code.
That's how it looks to the compiler:
func :: Ord a => [a] -> [[a]]
func xs = f1 d [a]
f1 [] ys = [c]
f1 xs ys | a >= b = d `f1` a:ys
| otherwise = c: d `f2` [a]
f2 [] ys = [c]
f2 xs ys | a < b = d `f2` a:ys
| otherwise = c : d `f1` [a]
where a = head xs
b = head ys
c = reverse ys
d = tail xs
So for the compiler, the lines in the where clause after the first look like continuations of that line, and of course you can't have multiple = without an intervening semicolon on one line.
You should never mix tabs and spaces (you shouldn't ever use tabs, actually). And if you use tabs, configure your editor to interpret them as eight spaces.
And, the where clause only scopes over the last equation, so there are no a, b, c, d in scope in the first four equations for func.
You have a more fundamental problem than indentation: a where block is local to a single function case. You're trying to use your where block to provide bindings (e.g. a, b, c, d) to a whole bunch of functions. This won't work.
To clarify, this correctly indented code won't work:
foo :: Int -> Int
foo 0 = a
foo 1 = b
where a = 2
b = 3
You'll get an error like Not in scope: `a'. This is because the where only extends over the foo 1 case; it doesn't even go to the foo 0 case, much less any other function.
Your code, on the other hand, seems to expect the where block to work for all your functions. To have bindings that can be seen by different functions, you have to put them at the same level of scope as the functions themselves.
Also, Haskell indentation is a little finnicky. You really should avoid tabs; it also really helps to have an editor that understands Haskell properly. I've found Emacs is very good here--I never have to worry about Haskell indentation with Emacs.
Emacs might have a bit of a learning curve (you should do the tutorial), but I think it's well worth it. You'll also have to install the Haskell mode. If you get the newest version of Emacs, you should be able to do this using the package manager.
Your error messages are because you're mixing tabs and spaces. It's best to just use spaces.
Now, if you're writing
a = head xs
b = head ys
c = reverse ys
d = tail xs
then
xs = (a:ds)
ys = (b:es)
Let's rewrite your function with pattern matching:
func :: Ord a => [a] -> [[a]]
func [] = []
func (a:ds) = f1 ds [a]
f1 [] ys = [reverse ys]
f1 (a:ds) (b:es) | a >= b = ds `f1` (a:b:es)
| otherwise = reverse (b:es): ds `f2` [a]
f2 [] ys = [reverse ys]
f2 (a:ds) (b:es) | a < b = ds `f2` (a:b:es)
| otherwise = reverse (b:es) : ds `f1` [a]
I know this is longer, but bear with me. f1 is really the same as f2, but with the comparison changed. Let's get a function no to negate a comparison, so that (no (>=)) x y = not (x >= y):
no cmp x y = not (cmp x y)
In fact, we can write this as
no = ((not.).)
r = reverse
func' (a:ds) = f (>=) ds [a]
f :: Ord a => (a -> a -> Bool) -> [a] -> [a] -> [[a]]
f _ [] ys = [r ys]
f cp (a:ds) ys#(b:es) | cp a b = f cp ds (a:ys)
| True = r ys : f (no cp) ds [a]
Now that is shorter.

Mapping which holds and passes previous result

When solving system of linear equations by Tridiagonal matrix algorithm in Haskell I met following problem.
We have three vectors: a, b and c, and we want to make a third vector c' which is a combination of them:
c'[i] = c[i] / b[i], i = 0
c'[i] = c[i] / (b[i] - a[i] * c'[i-1]), 0 < i < n - 1
c'[i] = undefined, i = n - 1
Naive implementation of the formula above in Haskell is as follows:
calcC' a b c = Data.Vector.generate n f
where
n = Data.Vector.length a
f i =
| i == 0 = c!0 / b!0
| i == n - 1 = 0
| otherwise = c!i / (b!i - a!i * f (i - 1))
It looks like this function calcC' has complexity O(n2) due to recurrence. But all we actualy need is to pass to inner function f one more parameter with previously generated value.
I wrote my own version of generate with complexity O(n) and helper function mapP:
mapP f xs = mapP' xs Nothing
where
mapP' [] _ = []
mapP' (x:xs) xp = xn : mapP' xs (Just xn)
where
xn = f x xp
generateP n f = Data.Vector.fromList $ mapP f [0 .. n-1]
As one can see, mapP acts like a standard map, but also passes to mapping function previously generated value or Nothing for first call.
My question: is there any pretty standard ways to do this in Haskell? Don't I reinvent the weel?
Thanks.
There are two standard function called mapAccumL and mapAccumR that do precisely what you want.
mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
Basically, they behave like a combination of fold and map.
map f = snd . mapAccumL (\_ x -> (() , f x) ()
foldl f b = fst . mapAccumL (\b x -> (f b x, () ) b
If you use Data.Array, which is lazy, you can express the recurrence directly by referring to c' while defining c'.
Following code seems to be the simplest implementation of formula above in my case:
import qualified Data.Vector.Generic as V
calcC' a b c = V.postscanl' f 0.0 $ V.zip3 a b c
where
f c' (a, b, c) = c / (b - a * c')
Thanks to the authors of Vector who added helpfull postscanl' method.

Resources