Haskell String to Maybe List - haskell

readSquareTransition :: String -> Maybe [SquareTurn]
readSquareTransition [] = Just []
readSquareTransition (x:xs) = case x of
'L' -> Just (L : readSquareTransition xs)
'R' -> Just (R : readSquareTransition xs)
_ -> Nothing
I want to get Just [L,L,R,R]. But looks like i failed :( Here is the error message!
src/StudentSources/LangtonsAnt.hs:231:24:
Couldn't match expected type ‘[SquareTurn]’
with actual type ‘Maybe [SquareTurn]’
In the second argument of ‘(:)’, namely ‘readSquareTransition xs’
In the first argument of ‘Just’, namely
‘(L : readSquareTransition xs)’
src/StudentSources/LangtonsAnt.hs:232:24:
Couldn't match expected type ‘[SquareTurn]’
with actual type ‘Maybe [SquareTurn]’
In the second argument of ‘(:)’, namely ‘readSquareTransition xs’
In the first argument of ‘Just’, namely
‘(R : readSquareTransition xs)’

A modular way of doing this would be to define readSquareTurn first which defines how to turn a Char into a single SquareTurn (with the possibility of failure):
readSquareTurn :: Char -> Maybe SquareTurn
readSquareTurn x = case x of
'L' -> Just L
'R' -> Just R
_ -> Nothing
and then use mapM :: (a -> Maybe b) -> [a] -> Maybe [b] to process the whole String like so:
readSquareTransition :: String -> Maybe [SquareTurn]
readSquareTransition = mapM readSquareTurn

Change this
'L' -> Just (L : readSquareTransition xs)
'R' -> Just (R : readSquareTransition xs)
to this
'L' -> fmap (L :) $ readSquareTransition xs
'R' -> fmap (R :) $ readSquareTransition xs
The problem is that readSquareTransition returns a Maybe [SquareTurn], so you can't apply (:) to it ((:) requires a List). fmap however lets you apply into the Just (while preserving a Nothing).

Related

Folding with anonymous functions

I'm currently trying to learn folding.
But instead of using predefined functions I want to use my own.
So I want to double all vowels in a String.
doubleVowels :: String -> String
My attempt is (yet just for 'a', as I'm try solve it for one letter first and will expand and optimize it, once it runs):
doubleVowels :: String -> String
doubleVowels a = foldl (\eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
Trying to run he code I'm getting the following erorr:
Experimenting.hs:8:78: error:
* Couldn't match type `[Char]' with `Char -> Char'
Expected type: Char -> Char
Actual type: String
* In the expression: a
In the expression: if eachChar == 'a' then (a ++ "aa") else a
In the first argument of `foldl', namely
`(\ eachChar -> if eachChar == 'a' then (a ++ "aa") else a)'
|
8 | doubleVowels a = foldl (\eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
| ^
Experimenting.hs:8:81: error:
* Couldn't match expected type `Char' with actual type `[Char]'
* In the second argument of `foldl', namely `""'
In the expression:
foldl
(\ eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
In an equation for `doubleVowels':
doubleVowels
= foldl
(\ eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
|
8 | doubleVowels a = foldl (\eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
| ^^
Failed, no modules loaded.
doubleVowels :: String -> String
doubleVowels a = foldr (\eachChar b -> if eachChar == 'a' then ("aa" ++ b) else (eachChar:b)) "" a
In most cases, if there is no specific reason for foldl, use foldr instead of foldl as it allows the Haskell compiler to lazily evaluate your expression. If I remember correctly, even then use foldl', since foldl is not strict and takes too much memory while not giving you any benefit for the laziness.
Apart from that, you are missing the second argument to foldrs (or foldls) function. foldr has type:
foldr :: (a -> b -> b) -> b -> t a -> b
The function to foldr has type a -> b -> b where the first argument is the current element of the folding structure and the second is the accumulator. The lambda that you are using has only one parameter.
In addition, the body of the lambda function also doesn't make much sense.
if eachChar == 'a' then (a ++ "aa") else a)
a is the parameter that the surrounding function doubleVowels receives. You need to use the parameters of the lambda function here.
First of all, the function used in foldl should have two argments. The first one is the accmulated result, and the other is current char.
Second, the order of evaluation of foldl is from left to right, so we have to reverse the result string.
For example, here is a modified version
doubleVowels :: String -> String
doubleVowels s = reverse $ foldl (\x y -> if y == 'a' then ("aa" ++ x) else (y : x)) "" s

Move One Element From one list to another In haskell

Morning i was doing an exercise it's my first time in Haskell
The exercise is to move the first element from my second list to the first position of my first list
Result: test [] [4,2,5,7]
=> ([4], [2,5,7])
That is my code :
test ::[a] -> [b] -> ([a],[b])
test [] [] = ([], [])
test [x] [] = ([x], [])
test [] [x] = ([x], [])
test [y] [x] = ([x:y], [])
But i got errors so please help me
this is my error
• Couldn't match expected type ‘[b]’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the type signature for:
pa :: forall a b. [a] -> [b] -> ([a], [b])
at Pushswap.hs:30:6
• In the second argument of ‘(:)’, namely ‘y’
In the expression: x : y
In the expression: [x : y]
• Relevant bindings include
x :: b (bound at Pushswap.hs:34:9)
y :: a (bound at Pushswap.hs:34:5)
pa :: [a] -> [b] -> ([a], [b]) (bound at Pushswap.hs:31:1)
Failed, modules loaded: none.
In the implementation
test [y] [x] = ([x:y], [])
y is of type a, x is of type b and [x:y] needs to be of type [a], hence the error.
You should be able to get past this error by making both lists the same type.

Couldn't match expected type [Int] Haskell

I am new to Haskell so I don't quite understand most of its errors. I have encountered an error trying to make a higher order function that uses foldl() to read a list and then multiply it by 2 (it automatically reverses it) and I use another another foldl() just to read it, in so reversing it to its original order.
I would be thankful for any help I receive.
here's the error
• Couldn't match expected type ‘[Int]’
with actual type ‘t0 Integer -> [Integer]’
• Probable cause: ‘foldl’ is applied to too few arguments
In the first argument of ‘reverses’, namely
‘(foldl (\ acc x -> (2 * x) : acc) [])’
In the expression: reverses (foldl (\ acc x -> (2 * x) : acc) [])
In an equation for ‘multthr’:
multthr = reverses (foldl (\ acc x -> (2 * x) : acc) [])
|
16 | multthr = reverses(foldl(\acc x-> (2*x):acc)[])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
here's the source code
reverses::[Int] ->[Int]
reverses = foldl(\acc x-> x:acc)[]
multthr::[Int]->([Int]->[Int])
multthr = reverses(foldl(\acc x-> (2*x):acc)[])
You need to compose your two foldl's with (.), instead of applying one to the other:
reverses :: [a] -> [a]
reverses = foldl (\acc x-> x:acc) []
---- multthr :: [Int] -> ([Int] -> [Int]) -- why??
multthr :: [Int] -> [Int]
---- multthr = reverses (foldl(\acc x-> (2*x):acc)[]) -- causes error
multthr = reverses . foldl (\acc x-> (2*x):acc) []
so that we have
> multthr [1..5]
[2,4,6,8,10]
it :: [Int]
(.) is the functional composition, defined as (f . g) x = f (g x).
Instead of doing the two foldl's you can do one foldr,
mult2 = foldr (\x r -> (2*x) : r) []
but then this is nothing else but, simply, map (2*).

haskell split function for multi-character delimeter

I've seen this code for the split function in Haskell already:
split :: String -> [String]
split [] = [""]
split (c:cs)
| c == ',' = "" : (split cs)
| otherwise = (c : head (split cs)) : tail (split cs)
Sample: Input: "1,2,3" Output:["1","2","3"]
However, this code only works when the delimeter is a ','. The code could be changed easily like this:
split :: Char->String -> [String]
split [] = [""]
split d (c:cs)
| c == d = "" : (split cs)
| otherwise = (c : head (split cs)) : tail (split cs)
So that the function works for any single character as the delimeter.
However, I want a function that works when the delimeter is a string itself.
So, I've tried this:
split' :: String -> String -> [String]
split' (d:ds) (c:cs)
| (d:ds) `isPrefixOf'` (c:cs) = "":rest
| otherwise = (c:head(split'((d:ds),rest))):tail(split'((d:ds),rest))
where
rest = split' (d:ds) drop( length(d:ds) (c:cs) )
where
isPrefixOf' :: (Eq a) => [a] -> [a] -> Bool
isPrefixOf' [] _ = True
isPrefixOf' _ [] = False
isPrefixOf' (x:xs) (y:ys)= (x == y) && (isPrefixOf' xs ys)
However, I get this ugly error when I load the program:
Prelude> :l testingsplit.hs
[1 of 1] Compiling Main ( testingsplit.hs, interpreted )
testingsplit.hs:15:27: error:
• Couldn't match expected type ‘[[Char]]’
with actual type ‘String -> [String]’
• Probable cause: ‘split'’ is applied to too few arguments
In the first argument of ‘head’, namely ‘(split' ((d : ds), rest))’
In the second argument of ‘(:)’, namely
‘head (split' ((d : ds), rest))’
In the first argument of ‘(:)’, namely
‘(c : head (split' ((d : ds), rest)))’
|
15 | | otherwise = (c:head(split'((d:ds),rest))):tail(split'((d:ds),rest))
| ^^^^^^^^^^^^^^^^^^^
testingsplit.hs:15:33: error:
• Couldn't match type ‘([Char], b0)’ with ‘[Char]’
Expected type: String
Actual type: ([Char], b0)
• In the first argument of ‘split'’, namely ‘((d : ds), rest)’
In the first argument of ‘head’, namely ‘(split' ((d : ds), rest))’
In the second argument of ‘(:)’, namely
‘head (split' ((d : ds), rest))’
|
15 | | otherwise = (c:head(split'((d:ds),rest))):tail(split'((d:ds),rest))
| ^^^^^^^^^^^^^
testingsplit.hs:15:54: error:
• Couldn't match expected type ‘[[Char]]’
with actual type ‘String -> [String]’
• Probable cause: ‘split'’ is applied to too few arguments
In the first argument of ‘tail’, namely ‘(split' ((d : ds), rest))’
In the second argument of ‘(:)’, namely
‘tail (split' ((d : ds), rest))’
In the expression:
(c : head (split' ((d : ds), rest)))
: tail (split' ((d : ds), rest))
|
15 | | otherwise = (c:head(split'((d:ds),rest))):tail(split'((d:ds),rest))
| ^^^^^^^^^^^^^^^^^^^
testingsplit.hs:15:60: error:
• Couldn't match type ‘([Char], b1)’ with ‘[Char]’
Expected type: String
Actual type: ([Char], b1)
• In the first argument of ‘split'’, namely ‘((d : ds), rest)’
In the first argument of ‘tail’, namely ‘(split' ((d : ds), rest))’
In the second argument of ‘(:)’, namely
‘tail (split' ((d : ds), rest))’
|
15 | | otherwise = (c:head(split'((d:ds),rest))):tail(split'((d:ds),rest))
| ^^^^^^^^^^^^^
testingsplit.hs:17:13: error:
• Couldn't match expected type ‘t0 -> t’
with actual type ‘[String]’
• The function ‘split'’ is applied to three arguments,
but its type ‘String -> String -> [String]’ has only two
In the expression: split' (d : ds) drop (length (d : ds) (c : cs))
In an equation for ‘rest’:
rest = split' (d : ds) drop (length (d : ds) (c : cs))
• Relevant bindings include
rest :: t (bound at testingsplit.hs:17:6)
|
17 | rest = split' (d:ds) drop( length(d:ds) (c:cs) )
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
testingsplit.hs:17:27: error:
• Couldn't match type ‘Int -> [a0] -> [a0]’ with ‘[Char]’
Expected type: String
Actual type: Int -> [a0] -> [a0]
• Probable cause: ‘drop’ is applied to too few arguments
In the second argument of ‘split'’, namely ‘drop’
In the expression: split' (d : ds) drop (length (d : ds) (c : cs))
In an equation for ‘rest’:
rest = split' (d : ds) drop (length (d : ds) (c : cs))
|
17 | rest = split' (d:ds) drop( length(d:ds) (c:cs) )
| ^^^^
testingsplit.hs:17:33: error:
• Couldn't match expected type ‘[Char] -> t0’
with actual type ‘Int’
• The function ‘length’ is applied to two arguments,
but its type ‘[Char] -> Int’ has only one
In the third argument of ‘split'’, namely
‘(length (d : ds) (c : cs))’
In the expression: split' (d : ds) drop (length (d : ds) (c : cs))
|
17 | rest = split' (d:ds) drop( length(d:ds) (c:cs) )
| ^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
I don't understand where I have gone wrong.
Also, I already know Data.List has the splitOn method, which does this already. However, I am not allowed to use that module for the work I am doing. I am only interested in answers that only use Haskell's Data.Char and the Prelude.
I have a follow-up question: How could I change split' so it works for any type of list in general. I'm not fully sure what type signature I should use.
I've tried this:
split'' :: Eq a => [a] -> [a] -> [[a]]
split'' _ [] = []
split'' [] x = map (:[]) x
split'' a#(d:ds) b#(c:cs)
| Just suffix <- a `stripPrefix'` b = "":split'' a suffix
| otherwise = if null rest
then [[c]]
else (c:head rest):tail rest
where
rest = split'' a $ tail b
stripPrefix' :: Eq a => [a] -> [a] -> Maybe [a]
stripPrefix' [] ys = Just ys
stripPrefix' (x:xs) (y:ys)
| x == y = stripPrefix' xs ys
stripPrefix' _ _ = Nothing
Now, I get this error about the Char type when I load the program:
[1 of 1] Compiling Main ( splittest.hs, interpreted )
splittest.hs:24:46: error:
• Couldn't match type ‘a’ with ‘Char’
‘a’ is a rigid type variable bound by
the type signature for:
split'' :: forall a. Eq a => [a] -> [a] -> [[a]]
at splittest.hs:20:1-38
Expected type: [[Char]]
Actual type: [[a]]
• In the second argument of ‘(:)’, namely ‘split'' a suffix’
In the expression: "" : split'' a suffix
In an equation for ‘split''’:
split'' a#(d : ds) b#(c : cs)
| Just suffix <- a `stripPrefix'` b = "" : split'' a suffix
| otherwise
= if null rest then [[c]] else (c : head rest) : tail rest
where
rest = split'' a $ tail b
• Relevant bindings include
suffix :: [a] (bound at splittest.hs:24:12)
rest :: [[a]] (bound at splittest.hs:29:7)
cs :: [a] (bound at splittest.hs:23:23)
c :: a (bound at splittest.hs:23:21)
b :: [a] (bound at splittest.hs:23:18)
ds :: [a] (bound at splittest.hs:23:14)
(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)
|
24 | | Just suffix <- a `stripPrefix'` b = "":split'' a suffix
| ^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
I'm new to Haskell, so I don't know where I have made a mistake.
Also, thank you for your earlier reply. It was very helpful and detailed.
Your code has many things wrong with it, including bad spacing and repetition of (d:ds) and (c:cs) when you could just give the whole thing a name by taking a#(d:ds) as an argument. However, these are all just stylistic errors. The biggest error in your code is the fact that you're trying to call functions like python, where it's the function name followed by parentheses followed by a comma separated list of arguments. Haskell does not work like this. Function arguments are separated by spaces, and you don't need parentheses after the function call. If you comma-separate arguments, you just create a tuple and call the function on that tuple, which breaks the whole thing. Here's your cleaned up code:
split' :: String -> String -> [String]
split' a#(d:ds) b#(c:cs)
| a `isPrefixOf'` b = "":rest
| otherwise = (c:head (split' a rest)):tail (split' a rest)
where
rest = split' a $ drop (length a) b
Isn't this much nicer to read? Unfortunately, this still doesn't work. rest already has split' a called on it, so you don't need to call split' a on it again in the body of your function:
split' :: String -> String -> [String]
split' a#(d:ds) b#(c:cs)
| a `isPrefixOf'` b = "":rest
| otherwise = (c:head rest):tail rest
where
rest = split' a $ drop (length a) b
Now, this compiles, but it still doesn't work:
λ> split' ", " "1, 2, 3"
["1 ","3*** Exception: Non-exhaustive patterns in function split'
This would be indicative of the fact that we have to add our base cases:
split' :: String -> String -> [String]
-- splitting nothing is nothing
split _ [] = []
-- splitting on empty string just returns array of individual chars
split [] x = map (:[]) x
split' a#(d:ds) b#(c:cs)
| a `isPrefixOf'` b = "":rest
| otherwise = (c:head rest):tail rest
where
rest = split' a $ drop (length a) b
Now, this compiles, but still has non-exhaustive patterns:
λ> split' ", " "1, 2, 3"
["1 ","3*** Exception: Non-exhaustive patterns in function split'
This time, it's because rest could be an empty list. So, we should check for that:
split' :: String -> String -> [String]
split _ [] = []
split [] x = map (:[]) x
split' a#(d:ds) b#(c:cs)
| a `isPrefixOf'` b = "":rest
| otherwise = if null rest
-- if rest is empty we default to just the one character
then [[c]]
else (c:head rest):tail rest
where
rest = split' a $ drop (length a) b
This still doesn't work, since we're removing the length of the delimiter every time, but we really only want to do that if we find a match. If we don't find a match, we should only drop one character.
The final working code is:
split' :: String -> String -> [String]
split' _ [] = []
split' [] x = map (:[]) x
split' a#(d:ds) b#(c:cs)
| a `isPrefixOf'` b = "":(split' a $ drop (length a) b)
| otherwise = if null rest
then [[c]]
else (c:head rest):tail rest
where
rest = split' a $ tail b
As a side note, your code can be cleaned up by using stripPrefix in Data.List instead of isPrefixOf', which allows you to save a drop and avoid iterating over the list twice:
import Data.List
split' :: String -> String -> [String]
split' _ [] = []
split' [] x = map (:[]) x
split' a#(d:ds) b#(c:cs)
| Just suffix <- a `stripPrefix` b = "":split' a suffix
| otherwise = if null rest
then [[c]]
else (c:head rest):tail rest
where
rest = split' a $ tail b
It's also pretty easy to implement yourself:
stripPrefix :: Eq a => [a] -> [a] -> Maybe [a]
stripPrefix [] ys = Just ys
stripPrefix (x:xs) (y:ys)
| x == y = stripPrefix xs ys
stripPrefix _ _ = Nothing
Here's the generic version:
import Data.List
split' :: (Eq a) => [a] -> [a] -> [[a]]
split' _ [] = []
split' [] x = map (:[]) x
split' a#(d:ds) b#(c:cs)
| Just suffix <- a `stripPrefix` b = []:split' a suffix
| otherwise = if null rest
then [[c]]
else (c:head rest):tail rest
where
rest = split' a $ tail b

Higher order functions in haskell error

selectMenu :: Int->IO()
selectMenu num
|(num==1)=convertFromDecimal
|(num==2)=--menu2
|(num==3)=putStrLn("3")
|(num==4)=putStrLn("4")
|(num==5)=putStrLn("5")
convertFromDecimal:: IO()
convertFromDecimal= do
putStrLn("\n\tConvert From Decimal To Binary & Octals \n")
putStrLn("----------------------------------------------------------\n")
putStrLn("Enter 5 decimal numbers [,,] : ")
input<-getLine
let n=(read input)::[Int] -- is this right?
--putStrLn (show n)
let result = convertionTO decToOct n
putStrLn(show result)`
decToOct :: Int -> [Int]
decToOct x = reverse(decToOct' x)
where
decToOct' 0 = []
decToOct' y = let (a,b) = quotRem y 8 in [b] ++ decToOct' a
convertionTO :: (Int -> [Int] -> [Int]) -> [Int] -> [Int]
convertionTO _ [] = []
convertionTO f (x:xs) = f x : convertionTO f xs
I correct those mistakes. I did update the question after correcting those errors. But this time it gives this error
How can i fix this error?
Assignment.hs:49:51:
Couldn't match expected type `[Int] -> [Int]'
with actual type `[Int]'
Expected type: Int -> [Int] -> [Int]
Actual type: Int -> [Int]
In the first argument of `convertionTO', namely `decToOct'
In the expression: convertionTO decToOct n
Assignment.hs:66:25:
Couldn't match expected type `Int'
with actual type `[Int] -> [Int]'
In the return type of a call of `f'
In the first argument of `(:)', namely `f x'
In the expression: f x : convertionTO f xs
(I'm copying the errors here in case you edit the question again.)
The first error
Assignment.hs:49:51:
Couldn't match expected type `[Int] -> [Int]'
with actual type `[Int]'
Expected type: Int -> [Int] -> [Int]
Actual type: Int -> [Int]
In the first argument of `convertionTO', namely `decToOct'
In the expression: convertionTO decToOct n
refers to this line of code
let result = convertionTO decToOct n
conversionTO expects its first argument to have the type Int -> [Int] -> [Int], but decToOct instead has the type Int -> [Int].
The second error
Assignment.hs:66:25:
Couldn't match expected type `Int'
with actual type `[Int] -> [Int]'
In the return type of a call of `f'
In the first argument of `(:)', namely `f x'
In the expression: f x : convertionTO f xs
refers to this line of code
convertionTO f (x:xs) = f x : convertionTO f xs
convertionTO produces an [Int], so the first argument to : must be an Int. But f x instead has type [Int] -> [Int].
How to fix these?
I'm going to assume that your line 49 is correct, and that the type signature for convertionTO is wrong. In that case it should be
convertionTO :: (Int -> [Int]) -> [Int] -> [Int]
This doesn't fix the second error, as f x now has type [Int].
The problem here is your use of :. : joins a single element to the start of a list. What you have is two lists that you want to join together. For this, use ++.
convertionTO f (x:xs) = f x ++ convertionTO f xs
Finally, note that your convertionTO is in the standard library as concatMap, which combines map with concat.
Those errors mean that you're referring to functions which don't exist. Either because you mistyped their names, or because you haven't defined them yet.
For example, instead of showresult, you probably meant show result, and I think you meant decToOct' instead of decToAny'. I can't see any references to convertToDecimal anywhere in the code you posted, so that error is probably somewhere else.

Resources