++ operator with String and IO String - string

explandDol :: String -> String -> [String] -> IO String
explandDol conclusion operators atoms =
let (ys,zs) = splitAt (head (take 1 replacement)) conclusion in ys ++ getConclusion operators atoms ++ (tail zs)
where replacement = elemIndices '$' conclusion
getConclusion :: String -> [String] -> IO String
getConclusion operators atoms =
runRVar (choice [atom1 ++ " " ++ [operator] ++ " " ++ atom2 | atom1 <- atoms, atom2 <- atoms, operator <- operators,checkAtoms atom1 atom2]) StdRandom
Is there a good way to fix this? I am getting this error:
/home/joe/Documents/haskell/LAG/main/main.hs: line 73, column 69:
Couldn't match expected type `IO String' with actual type `[Char]'
In the expression: ys ++ getConclusion operators atoms ++ (tail zs)
In the expression:
let (ys, zs) = splitAt (head (take 1 replacement)) conclusion
in ys ++ getConclusion operators atoms ++ (tail zs)
In an equation for `explandDol':
explandDol conclusion operators atoms
= let (ys, zs) = splitAt (head (take 1 replacement)) conclusion
in ys ++ getConclusion operators atoms ++ (tail zs)
where
replacement = elemIndices '$' conclusion
/home/joe/Documents/haskell/LAG/main/main.hs: line 73, column 75:
Couldn't match expected type `[Char]' with actual type `IO String'
In the return type of a call of `getConclusion'
In the first argument of `(++)', namely
`getConclusion operators atoms'
In the second argument of `(++)', namely
`getConclusion operators atoms ++ (tail zs)'
/home/joe/Documents/haskell/LAG/main/main.hs: line 73, column 75:
Warning: Redundant bracket
Found:
getConclusion operators atoms ++ (tail zs)
Why not:
getConclusion operators atoms ++ tail zs

Because value returned by getConclusion is IO String you cannot simply use it with functions operating on unwrapped values. Either first unwrap value using x <- getConclusion operators atom or if you want function composition use fmap.

Related

haskell show with function application

this line of code in Haskell produces an error on compilation:
lineStat :: String -> [String]
lineStat xs = zipWith (\n line -> show n ++ " " ++ show $ length line) [1..] $ lines xs
Error:
Couldn't match expected type Int -> String with actual type [Char]
The first argument of ($) takes one argument,but its type [Char] has none
However this line of code works:
lineStat xs = zipWith (\n line -> show n ++ " " ++ show (length line)) [1..] $ lines xs
Why?
It's a precedence issue.
show n ++ " " ++ show $ length line
means
(show n ++ " " ++ show) (length line)
which makes no sense since show is not a string. It does not mean
show n ++ " " ++ (show (length line))
To get the wanted one, you need parentheses. Use one of these:
zipWith (\n line -> show n ++ " " ++ show (length line)) [1..] $ lines xs
-- or
zipWith (\n line -> show n ++ " " ++ (show $ length line)) [1..] $ lines xs
I'd prefer the former since it's simpler.
Your problem boils down to:
*Main> let line = "abc"
*Main> " " ++ show (length line)
" 3"
*Main> " " ++ show $length line
<interactive>:9:1: error:
• Couldn't match expected type ‘Int -> t’ with actual type ‘[Char]’
The root cause for this is that $ has lower precedence than ++:
*Main> :info (++)
...
infixr 5 ++
*Main> :info ($)
...
infixr 0 $
as defined in the Haskell Report
Therefore, you need parentheses around show $ length line.

Haskell in append few list together

I want to the value of one element in a List , So I did the
changePoint :: (Int,Int) -> [[[Char]]] -> [[Char]]
changePoint (x,y) maze = let
linelement = maze !! (y-1)
-- value ["X"," "," ",...," ","X"]
rowelement = chunksOf 1 $ head linelement
-- type:[[a]]; value ["X"," "," "," "," "," "," "," "," "," "," "," "," ","X"]
l = length rowelement
list = take (x-1) rowelement
-- in take (x-1) rowelement -- ["X"]
in take (x-1) rowelement ++ (["."] : (drop (x) rowelement))
I want to append the list "take (x-1) rowelement" and "["."]" and "drop (x) rowelement", the type of list will be [[a]]
Couldn't match expected type ‘Char’ with actual type ‘[Char]’
In the expression: "."
In the first argument of ‘(:)’, namely ‘["."]’
In the second argument of ‘(++)’, namely
‘(["."] : (drop (x) rowelement))’ Failed, modules loaded: none.
x = 2 .
I know the problem is "["."]",but I really don't how to fix it .
The true return should be ["X","."," "," ",..,"X" ]
In GHCI, you can use :t somefunction to get the type of somefunction.
Here, the problem is with (:), lets see what GHCI tells us.
Prelude λ> :t (:)
(:) :: a -> [a] -> [a]
So (:) takes an a, a list of as and returns a new list. Specialized for the use case at hand, (:) has type [Char] -> [[Char]] -> [[Char]] (because a = [Char]). But ["."] has type [[Char]], so it does not match what's expected for (:).
Now, if you use take (x-1) rowelement ++ ("." : (drop (x) rowelement)) (note the missing [] around "."), the function should compile fine.
Either use:
(take (x-1) rowelement) ++ ["."] ++ (drop x rowelement)
Or
(take (x-1) rowelement) ++ ("." : (drop x rowelement))
The [ and ] are not necessary

Haskell head/tail vs pattern matching

Here are two pieces of code.
Working:
joins :: [String] -> String -> String
joins [] _ = ""
joins [x] _ = x
joins xs d = head xs ++ d ++ (joins (tail xs) d)
Not working:
joins :: [String] -> String -> String
joins [] _ = ""
joins [x] _ = x
joins [x:xs] d = x ++ d ++ (joins xs d)
The error log for the latter is:
test.hs:4:18:
Couldn't match expected type `[Char]' with actual type `Char'
In the first argument of `(++)', namely `x'
In the expression: x ++ d ++ (joins xs d)
In an equation for `joins':
joins [x : xs] d = x ++ d ++ (joins xs d)
test.hs:4:35:
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: [Char]
In the first argument of `joins', namely `xs'
In the second argument of `(++)', namely `(joins xs d)'
In the second argument of `(++)', namely `d ++ (joins xs d)'
What am I missing here?
Use parentheses, not brackets:
-- vvvvvv
joins (x:xs) d = x ++ d ++ (joins xs d)
The pattern [x:xs] matches only with a list of length one, whose single element is a nonempty list x:xs.
Since yours is a list of strings, [x:xs] matches with ["banana"] (where x='b', xs="anana"), with ["a"] (x='a', xs="") but not with ["banana", "split"] nor with [""].
This is clearly not what you want, so use plain parentheses.
(By the way, the parentheses in ... ++ (joins xs d) are not needed: function application binds more than any binary operator in Haskell.)

Haskell beginner cannot match expected type

I need to write a program which decodes a list of four values, which can be either I or O into a list of [Either Bool Bool]. I know I have to use maybe, but I simply cannot wrap my head around it. Right now I am totally desperate because I simply cannot solve this problem.
An example input and output might look like this: [I,O,O,I] => [Left True, Right False]
Here is the current code I have:
module Blueprint where
import Prelude
import Data.Maybe
data Bit = O | I deriving (Eq, Show)
encode :: [Either Bool Bool] -> [Bit]
encode [] = []
encode l = case head l of
Left False -> [I, I] ++ encode (tail l)
Left True -> [I, O] ++ encode (tail l)
Right False -> [O, I] ++ encode (tail l)
Right True -> [O, O] ++ encode (tail l)
decode :: [Bit] -> Maybe [Either Bool Bool]
decode [] = Nothing
decode [x] = Nothing
decode l = if isNothing (decode (tail (tail l)))
then Nothing
else case head l of
I -> if l!!1 == I
then [Left False] ++ decode (tail (tail l))
else [Left True] ++ decode (tail (tail l))
O -> if l!!1 == I
then [Right False] ++ decode (tail (tail l))
else [Right True] ++ decode (tail (tail l))
and these are the errors I get:
Prelude> :load serialise
[1 of 1] Compiling Blueprint ( serialise.hs, interpreted )
serialise.hs:22:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either Bool b0]'
In the expression: [Left False] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
In a case alternative:
I -> if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
serialise.hs:22:33:
Couldn't match expected type `[Either Bool b0]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Left False] ++ decode (tail (tail l))
serialise.hs:23:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either Bool b1]'
In the expression: [Left True] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
In a case alternative:
I -> if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
serialise.hs:23:32:
Couldn't match expected type `[Either Bool b1]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Left True] ++ decode (tail (tail l))
serialise.hs:25:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either a0 Bool]'
In the expression: [Right False] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
In a case alternative:
O -> if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
serialise.hs:25:34:
Couldn't match expected type `[Either a0 Bool]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Right False] ++ decode (tail (tail l))
serialise.hs:26:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either a1 Bool]'
In the expression: [Right True] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
In a case alternative:
O -> if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
serialise.hs:26:32:
Couldn't match expected type `[Either a1 Bool]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Right True] ++ decode (tail (tail l))
Failed, modules loaded: none.
Right now anything that helps me solve this problem is welcome. I have tried this for the better part of the day and I simply can't solve it.
You need to put a Just before your case statement to convert those values to Maybe [Either Bool Bool] instead of just [Either Bool Bool]:
decode :: [Bit] -> Maybe [Either Bool Bool]
decode [] = Nothing
decode [x] = Nothing
decode l = if isNothing (decode (tail (tail l)))
then Nothing
else Just $ case head l of
I -> if l!!1 == I
then [Left False] ++ decode (tail (tail l))
else [Left True] ++ decode (tail (tail l))
O -> if l!!1 == I
then [Right False] ++ decode (tail (tail l))
else [Right True] ++ decode (tail (tail l))
But this won't solve all of it. You also have decode embedded in that computation, and its type is Maybe [Either Bool Bool], but to use ++ you need just the [Either Bool Bool] as ++ only works with lists. This is where the Maybe monad comes in handy:
decode [] = Nothing
decode [x] = Nothing
decode (x:y:rest) = do
end <- decode rest
let this = case (x, y) of
(I, I) -> Left False
(I, O) -> Left True
(O, I) -> Right False
(O, O) -> Right True
return (this : end)
The case statement here is really just a different way of writing your case/nested-ifs. I also used pattern matching to avoid all the uses of head, !!, and tail since those functions should usually be avoided (they call error instead of doing proper error handling using Maybe). The <- syntax for Maybe will exit the computation early if Nothing is returned, so end <- decode rest is the same as saying if isNothing (decode rest) then Nothing else <continue>. Then, instead of building the entire result in each branch of the case/ifs, just compute the single result from x and y, then build the result list at the end.

Debugging type errors in GHC and Haskell function application

I was solving 10th problem from 99 problems in Haskell.
My solution was
-- Problem 10
encode:: String -> [(Int, Char)]
encode [] = []
encode (x:xs) = (length $ x : takeWhile (==x) xs, x) : encode $ dropWhile (==x) xs
The error that I got was
Prelude> :l 10-20.hs
[1 of 1] Compiling Main ( 10-20.hs, interpreted )
10-20.hs:4:17:
Couldn't match expected type `[Char] -> [(Int, Char)]'
with actual type `[(Int, Char)]'
The first argument of ($) takes one argument,
but its type `[(Int, Char)]' has none
In the expression:
(length $ x : takeWhile (== x) xs, x) : encode
$ dropWhile (== x) xs
In an equation for `encode':
encode (x : xs)
= (length $ x : takeWhile (== x) xs, x) : encode
$ dropWhile (== x) xs
10-20.hs:4:56:
Couldn't match expected type `[(Int, Char)]'
with actual type `String -> [(Int, Char)]'
In the second argument of `(:)', namely `encode'
In the expression: (length $ x : takeWhile (== x) xs, x) : encode
In the expression:
(length $ x : takeWhile (== x) xs, x) : encode
$ dropWhile (== x) xs
Failed, modules loaded: none.
Once I changed the code to
-- Problem 10
encode:: String -> [(Int, Char)]
encode [] = []
encode (x:xs) = (length $ x : takeWhile (==x) xs, x) : encode (dropWhile (==x) xs)
It compiles and run fine. Notice I just changed encode $ dropWhile (==x) xs to encode (dropWhile (==x) xs)
I have two questions here
How do I infer the change that I did (removing the $ application) from the GHCi error shown? I am unable to decipher this from the error thrown
Why does removing the $ work here?
($) performs function application with very low precedence, so
(length $ x : takeWhile (==x) xs, x) : encode $ dropWhile (==x) xs
is equivalent to
((length $ x : takeWhile (==x) xs, x) : encode) (dropWhile (==x) xs)
Which is ill-typed for two reasons. Firstly,
((length $ x : takeWhile (==x) xs, x) : encode)
would be a list built with the outermost (:), and not a function, and so it cannot be applied (thus the first error about the "first argument of ($)" which should take one argument). Secondly, encode is a String -> [(Int, Char)] function, and so it can't be the second argument of the outermost (:) (which should be a [(Int, Char)] given the type of the first argument, thus the second error).

Resources