I am new Haskell learner, and trying to do count words, but there are errors. how can i change to code and show the result like this
countWords ["friend","she","she"]
>[("friend",1),("she",2)
here is code
Prelude Data.List> countWords xs = map(\w -> (head w, length w))
$group $ sort $ words xs
Prelude Data.List> countWords ["hello", "hello", "world"]
:101:13: error:
• Couldn't match expected type ‘Char’ with actual type ‘[Char]’
• In the expression: "hello"
In the first argument of ‘countWords’, namely
‘["hello", "hello", "world"]’
In the expression: countWords ["hello", "hello", "world"]
:101:22: error:
• Couldn't match expected type ‘Char’ with actual type ‘[Char]’
• In the expression: "hello"
In the first argument of ‘countWords’, namely
‘["hello", "hello", "world"]’
In the expression: countWords ["hello", "hello", "world"]
:101:31: error:
• Couldn't match expected type ‘Char’ with actual type ‘[Char]’
• In the expression: "world"
In the first argument of ‘countWords’, namely
‘["hello", "hello", "world"]’
In the expression: countWords ["hello", "hello", "world"]
Thank you
As #chi said - words :: String -> [String] so either change the input type for your function to a single string of words separated by whitespace, or omit the words part, i.e.
countWords :: [String] -> [(String,Int)]
countWords xs = map (\w -> (head w, length w)) $ group $ sort xs
an example usage for this:
Prelude Data.List> countWords ["hello", "hello", "world"]
> [("hello",2),("world",1)]
or
countWords :: String -> [(String,Int)]
countWords xs = map (\w -> (head w, length w)) $ group $ sort $ words xs
an example usage:
Prelude Data.List> countWords "hello hello world"
> [("hello",2),("world",1)]
Let's break this down to a simpler example:
Prelude> xs = ["hello", "hello", "world"]
Prelude> words xs
<interactive>:2:7: error:
• Couldn't match type ‘[Char]’ with ‘Char’
Expected type: String
Actual type: [[Char]]
• In the first argument of ‘words’, namely ‘xs’
In the expression: words xs
In an equation for ‘it’: it = words xs
As you can see, we get a type error at the application of words. Further investigation shows us the problem:
Prelude> :t words
words :: String -> [String]
Prelude> :t xs
xs :: [[Char]]
Here we see the types for words and xs. First, words expects a String as its argument. However, xs type is [[Char]]. Since [Char] is the same as String, xs type can also be given as [String].
Now we see the problem. You are passing a [String] (a list of Strings) to a function which expects a single String.
Related
Reasoning about an error given in Haskell type error on compilation I found a strange behaviour of GHCi
test.hs
members :: String -> Bool;
members str = and [ b | x <- str, b <- map (elem x) "abcde" ]
produces the following error message
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:2:53: error:
• Couldn't match type ‘Char’ with ‘t0 Char’
Expected type: [t0 Char]
Actual type: [Char]
• In the second argument of ‘map’, namely ‘"abcde"’
In the expression: map (elem x) "abcde"
In a stmt of a list comprehension: b <- map (elem x) "abcde"
whereas
GHCi
Prelude> members :: String -> Bool; members xs = and [ b | x <- xs, b <- map (elem x) "abcde"]
produces
<interactive>:18:78: error:
• Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [[Char]]
Actual type: [Char]
• In the second argument of ‘map’, namely ‘"abcde"’
In the expression: map (elem x) "abcde"
In a stmt of a list comprehension: b <- map (elem x) "abcde"
Update
What I also do not understand, is why GHC omits the Foldable t0 class constraint - I
would have expected the error message be something like:
test.hs:2:53: error:
• Couldn't match type ‘Char’ with ‘t0 Char’
Expected type: Foldable t0 => [t0 Char]
Actual type: [Char]
• In the second argument of ‘map’, namely ‘"abcde"’
In the expression: map (elem x) "abcde"
In a stmt of a list comprehension: b <- map (elem x) "abcde"
Introduced by the FTP (Foldable-Traversable-Proposal) function elem has
gotten a new type signature.
elem :: (Eq a, Foldable t) => a -> t a -> Bool
And it seems GHCi uses the ExtendedDefaultRules extension which can be deactivated by
:set -NoExtendedDefaultRules
This extension and trac:10971 makes Foldable and
Traversable default to [].
update
The class constraint is not shown, because the type checking for it is done at a later stage.
I'm in need of a function to convert a string like 'Hello World' from the console to an Integer , and convert the Integer back to a string.
import Data.Text (Text, chunksOf)
encodeInts :: String -> Integer
encodeInts = read . concatMap show . map ord . show
decodeInts :: Integer -> String
decodeInts = read . map chr . map read . chunksOf 2 . show
The encoding works, in decodInts however, I'm getting:
* Couldn't match type `Text' with `[Char]'
Expected type: Integer -> [String]
Actual type: Integer -> [Text]
* In the second argument of `(.)', namely `chunksOf 2 . show'
In the second argument of `(.)', namely
`map read . chunksOf 2 . show'
In the second argument of `(.)', namely
`map chr . map read . chunksOf 2 . show'
and
* Couldn't match type `[Char]' with `Text'
Expected type: Integer -> Text
Actual type: Integer -> String
* In the second argument of `(.)', namely `show'
In the second argument of `(.)', namely `chunksOf 2 . show'
In the second argument of `(.)', namely
`map read . chunksOf 2 . show' Failed, modules loaded: none. Prelude>
I have already tried using {-# LANGUAGE OverloadedStrings #-}
You get that error because chunksOf has the wrong type:
chunksOf 2 :: Text -> [Text]
Either use chunksOf from Data.List.Split or write your own:
chunksOf :: Int -> [a] -> [a]
chunksOf _ [] = []
chunksOf k xs = let (as, bs) = splitAt k xs
in as : chunksOf k bs
That being said, your function won't work. ord 'o' is 111, a three digit number. I would write simpler variants:
encodeInts :: String -> [Int]
encodeInts = map ord
decodeInts :: [Int] -> String
decodeInts = map chr
After all, the process to get [Int] from Integer is ambigous, even with fixed lengths, since the first character might have an ord less than 100.
If you only have ASCII (or at least no unicode) and no zero Chars in your string, you can use this
encodeInts :: String -> Integer
encodeInts = foldr (\c n -> n * 256 + toInteger (ord c)) 0
decodeInts :: Integer -> String
decodeInts = map (chr . fromInteger) $ takeWhile (> 0) $ map (`mod` 256) $ iterate (`div` 256)
In Haskell, I am trying to print a method which returns an Int. For now, mySum is just a stub because I'm trying to figure out how to print it.
I looked up how to do this and I saw putStr can print a String and show converts an Int to a String so I did this:
mySum :: [Int] -> Int
mySum _ = 0
main = putStr show mySum [1..5]
However, I am getting these errors:
Couldn't match expected type ‘([Int] -> Int) -> [Integer] -> t’
with actual type ‘IO ()’
Relevant bindings include main :: t (bound at weirdFold.hs:10:1)
The function ‘putStr’ is applied to three arguments,
but its type ‘String -> IO ()’ has only one
In the expression: putStr show mySum [1 .. 5]
In an equation for ‘main’: main = putStr show mySum [1 .. 5]
and
Couldn't match type ‘a0 -> String’ with ‘[Char]’
Expected type: String
Actual type: a0 -> String
Probable cause: ‘show’ is applied to too few arguments
In the first argument of ‘putStr’, namely ‘show’
In the expression: putStr show mySum [1 .. 5]
So how can I actually print the result of the method?
Because function application is left-associative, putStr show mySum [1..5] is implicitly parenthesized as ((putStr show) mySum) [1..5]. There are a few options; some are listed below.
Parenthesize explicitly: putStr (show (mySum [1..5]))
Use the right-associative function application operator $; one example is putStr $ show (mySum [1..5])
Use composition with $: putStr . show . mySum $ [1..5]
Use composition with parentheses: (putStr . show . mySum) [1..5]
I'm trying to get a function working that uses foldl
to go through a list of tuples and create a string from it.
I'm trying to create a similar function that already works using recursion.
Here is the code that I'm trying to compile:
citeBook :: (String, String, Integer) -> String
citeBook (name, titl, date) = (titl ++ " (" ++ name ++ ", " ++ show date ++ ")\n")
--Recursion function
-- function must be called with putStr in order for newlines to work
bibliography_rec :: [(String, String, Integer)] -> String
bibliography_rec [] = ""
bibliography_rec xs = (citeBook(head xs) ++ bibliography_rec (tail xs))
--foldl function
bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold [] = ""
bibliography_fold (x:xs) = foldl (++) citeBook(x) xs --ERROR HERE
So in the very last line of the provided code, I am trying to have foldl
use (++) as the operator in order to combine the strings in the list.
I'm using citeBook(x) as my base case, since x will be the first tuple
taken from the list. Note that citeBook(x) returns a string. Then continue
folding with the list xs.
Here are the errors I'm getting. I think my parameter types for foldl aren't
matching up with what is expected, but everything seems okay to me..
hw1.hs:28:34:
Couldn't match type `[a0]'
with `(String, String, Integer) -> String'
Expected type: ((String, String, Integer) -> String)
-> [a0] -> (String, String, Integer) -> String
Actual type: [a0] -> [a0] -> [a0]
In the first argument of `foldl', namely `(++)'
In the expression: foldl (++) citeBook (x) xs
In an equation for `bibliography_fold':
bibliography_fold (x : xs) = foldl (++) citeBook (x) xs
hw1.hs:28:48:
Couldn't match expected type `[[a0]]'
with actual type `(String, String, Integer)'
In the third argument of `foldl', namely `(x)'
In the expression: foldl (++) citeBook (x) xs
In an equation for `bibliography_fold':
bibliography_fold (x : xs) = foldl (++) citeBook (x) xs
hw1.hs:28:51:
Couldn't match expected type `(String, String, Integer)'
with actual type `[(String, String, Integer)]'
In the fourth argument of `foldl', namely `xs'
In the expression: foldl (++) citeBook (x) xs
In an equation for `bibliography_fold':
bibliography_fold (x : xs) = foldl (++) citeBook (x) xs
I appreciate any and all feedback. Thanks!
You gave foldl the (++) function which has type String -> String -> String. However the collection you're folding over, xs, has type [(String, String, Integer)], not type [String].
You could change bibliography_fold to
bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold [] = ""
bibliography_fold (x:xs) = foldl (++) (citeBook x) (map citeBook xs)
or just to
bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold xs = foldl (++) "" (map citeBook xs)
but I'm a relative noob at Haskell myself so take my coding style with a grain of salt.
Also, you need to write (citeBook x) and not citeBook(x), or the compiler will assume that citeBook and (x) are both arguments to foldl (correct me if I'm wrong). This helps explain why the error message you got is so strange-looking.
You've already gotten your answer, so I'll provide another way of using a fold to solve this problem:
bibliography_fold :: [(String, String, Integer)] -> String
bibliography_fold = foldr ((++) . citeBook) ""
There's no maps, no special cases, and it can be written in point free style. I'd encourage you to deconstruct this expression in GHCi and inspect each component using :info to explore how it actually works. Look at the types of foldr, ++, citeBook, (++) . citeBook, see if you can figure out why this works. You may want to look up the source code for foldr as well.
I want to make a first character of a string if it's not. This is what I'm doing:
import Data.Char
onlyCapitals :: [String] -> [String]
onlyCapitals [] = []
onlyCapitals (x:xs) = if isUpper $ head x
then x ++ onlyCapitals xs -- 1
else toUpper (head x) : tail x ++ onlyCapitals xs -- 2 and 3
main = print $ onlyCapitals ["Aaaa", "bbb", "ffff"]
And I got 3 errors:
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: String
Couldn't match type `Char' with `[Char]'
Expected type: String
Actual type: Char
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: String
The first thing to realize
(++) :: [a] -> [a] -> [a]
(:) :: a -> [a] -> [a]
So your first error is that you try to do something like String ++ [String] which is a type error, instead you want (:)
The next problem is
toUpper (head x) : tail x ++ onlyCapitals xs
The problem is the associativity and precedence of ++ and : are both the same level to the right. So this is parsed as
toUpper (head x) : (tail x ++ onlyCapitals xs)
this is fixed with explicit parens and switching ++ to : again
(toUpper (head x) : tail x) : onlyCapitals xs
Style notes
Now this works, except if you pass it an empty string in which case it'll crash. Instead maybe something like this would be nicer
onlyCapitals :: [String] -> [String]
onlyCapitals = map cap
where cap "" = ""
cap (x : xs) = toUpper x : xs
We abstract away the explicit recursion and construction of the list and just leave it to map. Then we properly handle "" and capitalize the first character of nonempty strings.
Let's take the line you marked -- 1: then x ++ onlyCapitals xs. The type of x is String, while the type of onlyCapitals xs is [String]. The ++ operator requires its two operands to be of the same type and it assumes them to be lists. The left operand is a [Char] and it then expect the right operand to be [Char] as well. As the right operand is in fact [String], which is [[Char]], it thus reports: "couldn't match type [Char] with [[Char]]", simplified to "couldn't match type Char with [Char]", as the 'outer' list could be matched.
So you don't want to use the ++ operator there, but rather the : operator. The other errors stem from a similar problem on the line marked -- 2 and 3 and the solution is to very carefully check what types your subexpressions have and in what order the operators are applied.
One note on this method: you don't actually need the conditional. toUpper on something that is already a capital works just fine, so the 'else' can just be applied to every member of the list.