I have a simple function in Haskell that takes a list of tuples like this: [(1,'a'),(2,'b')..(26,'z')], and returns a letter value based on the number input. So ideally,
getCharByNum 3
> "c"
I'm attempting this by using a list comprehension, and filtering out every tuple that doesn't contain that number.
zippedChars = zip [ x | x <- [1..26]] [ x | x <- ['a'..'z']]
getCharByNum :: (Integral a) => a -> [Char]
getCharByNum num = [ head vector | vector <- zippedChars, num == last vector ]
I think this makes sense...getCharByNum is a function that takes an Integer, and returns a (short) list of Chars. But GHCI throws this error:
Couldn't match expected type `[a]'
with actual type `(Integer, Char)'
In the first argument of `last', namely `vector'
In the second argument of `(==)', namely `last vector'
In the expression: num == last vector
How do you correctly construct a type signature that allows this function to run? (I know that this can be easily done with an index, or even more easily with Data.Char.ord, but I'm trying to understand list comprehensions better)
EDIT: I've cleaned the code a bit:
zippedChars = zip [1..26] ['a'..'z']
getCharByNum :: Integral -> [Char]
getCharByNum num = [ c | (n,c) <- zippedChars, num == n ]
But I am still getting this error:
folds.hs:50:18:
Expecting one more argument to `Integral'
In the type signature for `getCharByNum':
getCharByNum :: (Integral) -> [Char]
Failed, modules loaded: none.
This is a function that takes one Integer and returns a list of Chars, so I am not sure what I am missing.
Your problem is that you are using head and last, which apply to lists only, while your vector is a tuple. You need to use fst and snd instead. Or even better, you can use pattern matching:
getCharByNum num = [ c | (n,c) <- zippedChars, num == n ]
By the way, [ x | x <- [1..26]] is the same as just [1..26], and similarly for the character list.
Integral is a typeclass. Integral is not a type. a is an instance of Integral, so we declare this at the beginning of the signature.
zippedChars :: Integral a => [(a, Char)]
zippedChars = zip [1..26] ['a'..'z']
getCharByNum :: Integral a => a -> String
getCharByNum num = [ c | (n,c) <- zippedChars, num == n ]
>>> getCharByNum 3
'c'
A suggestion:
>>> ['a'..'z'] !! 4
'c'
Related
insert_at insert an element e into a list xs in specific location n
testgetting Left if n less than 0
test2 getting Left if n larger than xs's length or The type e isn't match the element's type in listxs. Otherwise passing Right xs to the next.
import Data.Typeable
insert_at :: a -> [a] -> Int -> [a]
insert_at e xs n = a++(e:b) where
t = splitAt n xs
a = fst t
b = snd t
test :: (Ord a, Num a) => b -> a -> Either [Char] b
test xs n = if n < 0 then Left "n<0" else Right xs
test2 :: (Typeable a1, Typeable a2) =>
a1 -> [a2] -> Int -> Either [Char] [a2]
test2 e xs n
| n> ( length xs )= Left "n> $ length xs "
| (typeOf e) /= (typeOf (head xs) ) = Left "(typeOf e) /= (typeOf (head xs) ) "
|otherwise = Right xs
sf :: Typeable a => a -> [a] -> Int -> Either [Char] [a]
sf e xs n = test xs n >>test2 e xs n >> Right (insert_at e xs n)
All the other error got properly handled, expect this.
* No instance for (Num Char) arising from the literal `1'
* In the expression: 1
In the second argument of `sf', namely `[1, 2, 3, 4, ....]'
In the expression: sf 'a' [1, 2, 3, 4, ....] 3
The error message states that you're trying to evaluate the expression sf 'a' [1, 2, 3, 4, ....] 3. Since this expression is not shown in your question, I'm assuming you're using it in GHCi to test out your code, right?
The type signature of sf says that the first parameter has type a, and the second parameter has type [a], which is a list whose elements are of the same type as the first parameter.
So the compiler sees that the first parameter is 'a'. That's a character, type Char.
"Got it," - thinks the compiler, - "now I know that a is Char. And now I know that the second parameter must have type [Char] - that is, a list of Char".
And yes, the second parameter is indeed a list, but wait! The first element of the list is not a character, but number 1! That does not compute!
Fortunately, number literals are special in Haskell. Number literals are not merely of type Int or even of type Integer, no! Numbers can be of any type as long as that type has an instance of class Num.
So since the compiler already knows that the elements of that list must be of type Char, but it sees a number literal, it concludes that it must now find an instance of class Num for type Char.
But there is no such instance! And so the compiler rightly complains: "no instance Num Char"
To fix the problem, I need to better understand what you were actually trying to do.
Did you intend the whole function to work on numbers? Then the first parameter must be a number, not a character.
Or did you intend it to work on characters? Then the second parameter must be a list of characters, not numbers.
Or did you intend the first two parameters not to be the same type at all? Then you must change the type signature of sf to indicate that.
sf expects a value and a list as its first two arguments. The elements of the list must have the same type as the first argument. This is the meaning of
sf :: a -> [a] -> ...
When you write sf 'a' [1], this means 1 and 'a' must have the same type. So the type checker looks for a way to interpret 1 as a Char; it fails, because this is not possible. Some fixes might include:
sf 'a' "1234" 3
sf 'a' [toEnum 1, toEnum 2, toEnum 3, toEnum 4] 3
sf (fromEnum 'a') [1, 2, 3, 4] 3
I'm new to Haskell and have a question about types, it error out because it couldn't match expected type. I believe squarePrime is a bool, correct me if i'm wrong and it is complaining because it wants a int? Can someone explain, thanks in advance.
squarePrimes n = [n^2 | (n) <- [2..n-1], (all (\a -> mod n a /= 0) [2..n-1])]
multiOfFive a = mod a 5 == 0
fun n = [n | n <-[1..n], multiOfFive || squarePrimes n]
The 'squarePrimes n' function returns a list of Integers, as opposed to a Bool or a list of Bools. Looking at the list comprehension:
[n^2 | (n) <- [2..n-1], (all (\a -> mod n a /= 0) [2..n-1])]
This will produce a list of n^2, of n pulled from the range [2..n-1], for every n that satisfies the condition:
(all (\a -> mod n a /= 0) [2..n-1])
Then, in the list comprehension used in the definition of 'fun':
[n | n <-[1..n], multiOfFive || squarePrimes n]
A list is being constructed of each n in the range 1 to n, as long as the following condition is true:
multiOfFive || squarePrimes n
Haskell is expecting this to evaluate to a Bool. However, 'multiOfFive' is being called without any argument, and 'squarePrimes n' returns a list of Integers, as opposed to a Bool.
Without knowing exactly what the intention of 'fun n' is, I have altered the provided code a little bit to get a list comprehension that loads without error:
fun n = [n | n <- [1..n], (multiOfFive n) || (elem n (squarePrimes n))]
Now, it uses the 'elem' function to check whether a given 'n' is an element of the list 'squarePrimes n'.
I believe squarePrimes is a Bool, correct me if I'm wrong
GHCi will tell you:
λ> let squarePrimes n = [n^2 | (n) <- [2..n-1], (all (\a -> mod n a /= 0) [2..n-1])]
λ> :t squarePrimes
squarePrimes :: Integral a => a -> [a]
It is complaining because it wants an int? Can someone explain
Here Integral i => i is any integer type. That could for example be Int or Integer. This is because the integer literals 0, 1, 2 and the arithmetic operators you use aren't restricted to a specific integer type.
You're using squarePrimes n as a Bool.
You're also using multiOfFive as a Bool when its type is:
λ> let multiOfFive a = mod a 5 == 0
λ> :t multiOfFive
multiOfFive :: Integral a => a -> Bool
so a function that takes an integer type and returns a Bool.
I want to get only the capital letters from a string, and had the idea to see if each letter in the string is contained in a list of all capital letters:
capsOnly = [ x| x<- string, (x elem ['A'..'Z'])]
the problem is that apparently Haskell does not recognize that the part behind the comma is supposed to be a condition for x, and gives me this:
* Couldn't match expected type `(a0 -> t0 a0 -> Bool)
-> [Char] -> Bool'
with actual type `Char'
* The function `x' is applied to two arguments,
but its type `Char' has none
In the expression: (x elem ['A' .. 'Z'])
In a stmt of a list comprehension: (x elem ['A' .. 'Z'])
So how do I define what is the Argument and what is the List where x comes from?
Or is that not possible?
I know that you can also do it like:
onlyCaps = [ x| x<- string, x < 'a']
but I really want to know if my first approach is possible, and how to write it if it is
The problem is not with the list comprehension itself. The problem is that x elem ['A'..'Z'] does not make much sense.
elem :: Eq a => a -> [a] -> Bool is a function that takes as input an element and a list and checks if the element belongs to the list.
So you should write it like:
capsOnly = [ x | x <- string, elem x ['A'..'Z']]
Or alternatively use backtics (to use infix notation):
capsOnly = [ x | x <- string, x `elem` ['A'..'Z']]
This however is not very efficient: it requires O(n) to check membership. Since we check a range, it is more efficient to do bound checks, like:
capsOnly = [ x | x <- string, x >= 'A', x <= 'Z']
This requires two comparisons that run in O(1) making it faster.
What we do here is filtering. Usually it is better (more descriptive and declarative) to use filter :: (a -> Bool) -> [a] -> [a] for this with isAsciiUpper :: Char -> Bool as predicate:
import Data.Char(isAsciiUpper)
capsOnly = filter isAsciiUpper string
I'm currently working on a board evaluator in haskell. I'm trying to use map with a function with multiple parameters; I've read other SO questions regarding this but keep getting type errors so perhaps I'm just misunderstanding the Haskell types (I'm a Python programmer). Either way, here's the code:
scorePiecesRow [] _ = 0
scorePiecesRow (x:xs) y
| x == y = 1 + (scorePiecesRow xs y)
| x == '-' = 0 + (scorePiecesRow xs y)
| otherwise = -1 + (scorePiecesRow xs y)
scorePieces [] _ = 0
scorePieces board y = foldr (+) 0 (map (scorePiecesRow y) board)
scorePiecesRow works just fine when I pass it anything like "wwwb--" 'w' (which returns 3), but as soon as I call scorePieces (e.g. scorePieces ["www", "bb-"] 'w' which should return 1), I get a bunch of type errors:
<interactive>:37:14:
Couldn't match expected type `Char' with actual type `[Char]'
In the expression: "www"
In the first argument of `scorePieces', namely `["www", "bb-"]'
In the expression: scorePieces ["www", "bb-"] 'w'
<interactive>:37:21:
Couldn't match expected type `Char' with actual type `[Char]'
In the expression: "bb-"
In the first argument of `scorePieces', namely `["www", "bb-"]'
In the expression: scorePieces ["www", "bb-"] 'w'
<interactive>:37:28:
Couldn't match expected type `[Char]' with actual type `Char'
In the second argument of `scorePieces', namely 'w'
In the expression: scorePieces ["www", "bb-"] 'w'
In an equation for `it': it = scorePieces ["www", "bb-"] 'w'
I'm a bit confused by the error messages. The first one tells me, for example, that it's expecting Char, but the first argument of scorePiecesRow takes [Char].
If anyone could shed some light on this, it would be greatly appreciated!
While Haskell will infer types for you, they're usually very valuable to write out as well to both document your code (in a machine checked fashion!) and check your assumptions. We can do the work of Haskell's type inference engine here to figure out what we know about these functions.
Since scorePiecesRow is added to a number in 1 + (scorePiecesRow xs y) we know the result must be in the typeclass Num (where (+) is defined)
scorePiecesRow :: Num a => ... -> a
Furthermore, by looking at the pattern matching in the arguments we can easily see that the first argument must be a list.
scorePiecesRow :: Num a => [b] -> ... -> a
and since we compare the elements of the first argument with the second argument using (==) we know they must be the same type and in the typeclass Eq (where (==) is defined!).
scorePiecesRow :: (Num a, Eq b) => [b] -> b -> a
Finally, the elements of the first argument are compared with equality to '-', so we know they actually must be Char. Since String is a synonym for [Char] we can impute that.
scorePiecesRow :: (Num a) => String -> Char -> a
We can do the same with scorePieces to learn that
scorePieces :: Num a => String -> String -> a
and this is where we see the problem. You're calling scorePieces ["www", "bb-"] 'w', i.e. with a [String] and a Char while scorePieces expects a String and another String.
The error is telling you exactly this, but it's a little confusing since String and [Char] are the same and GHC tends to reduce types to their simplest form when reporting errors.
Because scorePiecesRow takes as its arguments a [Char] and a Char, when, in your map function, you call scorePiecesRow y, Haskell decides that y must be of type [Char], as it is given as the first argument to scorePiecesRow.
This is the source of the third error message, as Haskell is expecting a [Char], but you give it a Char.
The first two are essentially the same thing, in that scorePiecesRow y expects a Char, and so, when you map this function over board, Haskell expects board to have type [Char], and it thus fails when you give it a board of type [[Char]].
Perhaps try the following:
scorePiecesRow _ [] = 0
scorePiecesRow y (x:xs)
| x == y = 1 + (scorePiecesRow y xs)
| x == '-' = 0 + (scorePiecesRow y xs)
| otherwise = -1 + (scorePiecesRow y xs)
scorePieces [] _ = 0
scorePieces board y = foldr (+) 0 (map (scorePiecesRow y) board)
or, if you want to keep your scorePiecesRow function the same,
scorePieces [] _ = 0
scorePieces board y = foldr (+) 0 (map (\row -> scorePiecesRow row y) board)
I'm trying to solve the 8 queens problem in Haskell without the use of any advanced functions, only with basic knowledge. I have come this far only but I'm getting an error that I can't understand.
The code:
queens = [[x1,x2,x3,x4,x5,x6,x7,x8] | x1<-[1..8], x2<-[1..8],
x3<-[1..8], x4<-[1..8], x5<-[1..8],
x6<-[1..8], x7<-[1..8], x8<-[1..8],
safeH [x2,x3,x4,x5,x6,x7,x8] x1]
safeH xs e = if length xs == 1 then head xs
else e /= safeH (tail xs) (head xs)
and the error message is:
y.hs:1:42:
No instance for (Num Bool) arising from the literal `1'
Possible fix: add an instance declaration for (Num Bool)
In the expression: 1
In the expression: [1 .. 8]
In a stmt of a list comprehension: x1 <- [1 .. 8]
[1 of 1] Compiling Main ( y.hs, interpreted )
Failed, modules loaded: none.
The culprit is
.........
safeH [x2,x3,x4,x5,x6,x7,x8] x1]
safeH xs e = if length xs == 1 then head xs
else e /= safeH (tail xs) (head xs)
specifically,
else e /= safeH (tail xs) (head xs)
because e == x1. So on the one hand safeH returns Bool, being used as a test in the list comprehension. OTOH you compare its result with x1. Which is 1, among other things (x1<-[1..8]). I.e. Num1. Which must also be a Bool. Hence the error.
1 A numeric literal such as 1 is parsed as a value of a polymorphic type Num a => a. I.e. its concrete type must belong to the Num type class. Since the concrete type is also determined to be Bool here, this means that Bool must belong to the Num type class, for this code to typecheck. Hence the instance for (Num Bool) is sought.
The if ... then ... else ... expression in safeH is not well-typed:
safeH l e = if length l == 1 then head l
else e /= safeH(tail l)(head l)
The then branch is incorrectly returning a numeric type, while the else branch is returning a boolean type Bool, as I think you intended.
You should add type signatures to all your top-level functions as a way of documenting what your code does, organizing your thoughts, and making errors easy to understand; the error message here is needlessly confusing because GHC infers that your code is returning some Num type thing from the first branch, and so when the second branch returns Bool GHC complains about the wrong thing: there being no instance of Num for the Bool type).
You should also read about pattern matching on lists, and take a look at the implementation of length and think about why it's not the best way to implement your function here.
So instead of using length and head, start with this framework:
safeH :: [Int] -> Int -> Bool
safeH [n] e = -- the case for a 1-length list
safeH (n:ns) e = -- ???
When you get something working then try redefining it where the base case is the empty list [].