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
Related
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'
My code:
isOrdered :: (a -> a -> Bool) -> [a] -> Bool
isOrdered mark xs =(head xs) `mark`(head(tail xs))
Compiles perfectly but when I try to call it with
isOrdered < [1,2,3]
I get an error:
Couldn't match expected type `(a0 -> a0 -> Bool) -> [a0] -> Bool'
with actual type `[t0]'
In the second argument of `(<)', namely `[1, 2, 3]'
In the expression: isOrdered < [1, 2, 3]
In an equation for `it': it = isOrdered < [1, 2, 3]
What am I missing here?
Since < is infix, you have to wrap it in parens. This converts it to be prefixed.
1 < 2 ==> (<) 1 2
1 + 5 ==> (+) 1 5
Then you're code becomes
isOrdered (<) [1, 2, 3]
This is actually part of a more general concept of sectioning. You can completely convert an infix operator to prefix with parens, or partially apply it like this
\x -> x + 1 ===> (+1)
\x -> 2 ^ x ===> (2^)
The only place where this goes a bit pear-shaped is with -. Since - is a super special prefix operator defined by the Haskell language, you can't do (-2), since it's not clear whether this is a section or a number. Haskell chooses a number, but if you want a section, there is a function subtract.
\x -> x - 2 ==> subtract 2
This works:
isOrdered (<) [1,2,3]
Not sure why, though. It’s a general thing:
Prelude> :type <
<interactive>:1:1: parse error on input `<'
Prelude> :type (<)
(<) :: Ord a => a -> a -> Bool
I’m sure others will explain.
When passing an operator to a higher level function, you have to surround it with parentheses:
isOrdered (<) [1, 2, 3]
You also have to do this for partially applied operators
map (== 2) [1, 2, 3]
This is not an answer to your question, but just a stylistic tip: idiomatic Haskell code should use pattern matching instead of head/tail. Pattern matching statically ensures that you don't accidentally try to access inexistent elements.
The way you would write your function using pattern matching is:
isOrdered :: (a -> a -> Bool) -> [a] -> Maybe Bool
isOrdered mark (x:y:_) = Just (x `mark` y)
isOrdered _ _ = Nothing
Note that I've included a case for when the list does not contain two elements and wrapped the result in a Maybe. This prevents run-time errors by forcing you to handle that case.
I have a tuple (1, 2, 3) and want to get the third element, however, I keep getting type errors.
Please see the below code:
third (hd : tl) = snd tl
third tpl = head$tail$tail tpl
How can I fix the type errors that are occuring and get the third element correctly?
Tuples aren't lists
In you're code, you're manipulating lists, :, head and tail all work on lists. So
third tpl = head . tail . tail . tail $ tpl
third' (_:_:x:_) = x
Will give you the third element.
a = [1, 2, 3]
>> third a
3
>> third (1, 2, 3)
Error expecting list, but got tuple
Instead you're going to have to use a function of type
thd :: (a, b, c) -> c
This function doesn't exist in the standard libs, it's completely trivial
thd (_, _, a) = a
And that's it :)
You're getting tuples confused with lists:
-- Tuples: Fixed length, mixed types, uses parenthesis
myTuple :: (Int, String)
myTuple = (1, "Hello")
-- Lists: Variable length, single type, uses square brackets
myList :: [Int]
myList = [1, 2, 3, 4]
-- Pattern matching a 3-tuple
isRightTriangle :: (Int, Int, Int) -> Bool
isRightTriangle (a, b, c) = a^2 + b^2 == c^2
-- Pattern matching a 2-tuple
name :: (String, Int) -> String
name (n, a) = n
-- or: name = fst
age :: (String, Int) -> Int
age (n, a) = a
-- or: age = snd
-- Pattern matching a list
thirdElem :: [a] -> a
thirdElem (x1:x2:x3:xs) = x3
thirdElem _ = error "List must have at least 3 elements"
-- or: thirdElem xs = head $ tail $ tail xs
If you haven't already, you should check out Learn You a Haskell For Great Good. It's a great, fun to read introduction to Haskell, starting out with the basic types like strings, tuples, numbers, and lists.
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 [].
I'm trying to write a program in Haskell
that gets a list (of integer) and prints out the number of elements that are bigger than the list's average
So far I tried
getAVG::[Integer]->Double
getAVG x = (fromIntegral (sum x)) / (fromIntegral (length x))
smallerThanAVG:: [Integer]->Integer
smallerThanAVG x = (map (\y -> (if (getAVG x > y) then 1 else 0)) x)
For some reason I'm getting this error
Couldn't match expected type `Double'
against inferred type `Integer'
Expected type: [Double]
Inferred type: [Integer]
In the second argument of `map', namely `x'
It could be that I haven't written the logic correctly, although I think I did..
Ideas?
These errors are the best kind, because they pinpoint where you have made a type error.
So let's do some manual type inference. Let's consider the expression:
map (\y -> (if (getAvg x > y) then 1 else 0)) x
There are a few constraints we know off the bat:
map :: (a -> b) -> [a] -> [b] -- from definition
(>) :: Num a => a -> a -> Bool -- from definition
getAvg :: [Integer] -> Double -- from type declaration
1, 0 :: Num a => a -- that's how Haskell works
x :: [Integer] -- from type declaration of smallerThanAVG
Now let's look at the larger expressions.
expr1 = getAvg x
expr2 = (expr1 > y)
expr3 = (if expr2 then 1 else 0)
expr4 = (\y -> expr3)
expr5 = map expr4 x
Now let's work backwards. expr5 is the same as the RHS of smallerThanAVG, so that means it has the same result type as what you've declared.
expr5 :: Integer -- wrong
However, this doesn't match our other constraint: the result of map must be [b] for some b. Integer is definitely not a list (although if you get facetious, it could be coerced into a list of bits). You probably meant to sum that list up.
expr6 = sum expr5
sum :: Num a => [a] -> a
Now let's work forwards.
expr1 :: Double -- result type of getAvg
y :: Double -- (>) in expr2 requires both inputs to have the same type
expr4 :: (Integer -> [a]) -- because for `map foo xs` (expr5)
-- where xs :: [a], foo must accept input a
y :: Integer -- y must have the input type of expr4
Herein lies the conflict: y cannot be both a Double and an Integer. I could equivalently restate this as: x cannot be both a [Double] and [Integer], which is what the compiler is saying. So tl;dr, the kicker is that (>) doesn't compare different types of Nums. The meme for this sort of problem is: "needs more fromIntegral".
(getAvg x > fromIntegral y)
Your code has two errors.
Although the type signature in the code declares that smallerThanAVG x evaluates to an Integer, its code is map ... x, which clearly evaluates to a list instead of a single Integer.
In the code getAVG x > y, you are comparing a Double to an Integer. In Haskell, you can only compare two values of the same type. Therefore, you have to use fromIntegral (or fromInteger) to convert an Integer to a Double. (This is essentially what caused the error message in the question, but you have to get used to it to figure it out.)
There are several ways to fix item 1 above, and I will not write them (because doing so would take away all the fun). However, if I am not mistaken, the code you are aiming at seems like counting the number of elements that are smaller than the average, in spite of what you write before the code.
Styling tips:
You have many superfluous parentheses in your code. For example, you do not have to parenthesize the condition in an if expression in Haskell (unlike if statement in C or Java). If you want to enjoy Haskell, you should learn Haskell in a good style instead of the Haskell which just works.
You call the variable which represents a list “x” in your code. It is conventional to use a variable name such as xs to represent a list.
Others have explained the errors beautifully.
I'm still learning Haskell but I'd like to provide an alternative version of this function:
greaterThanAvg :: [Int] -> [Int]
greaterThanAvg xs = filter (>avg) xs
where avg = sum xs `div` length xs
cnt = length $ greaterThanAvg [1,2,3,4,5]