I'm beginning to learn Haskell with "Learn You a Haskell for Great Good!" and I've made a strange mistake, which I can't find the reason for.
Here is the code I typed:
let xs = [if x < 3 then "bang" else "boom" | x <- xs]
And the the text of the error in GHCi:
No instance for (Num [Char])
arising from the literal `3'
Possible fix: add an instance declaration for (Num [Char])
In the second argument of `(<)', namely `(3)'
In the expression: x < (3)
In the expression: if x < (3) then "bang" else "boom"
But when I type:
let boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
which is the example of the book, I don't have any problem.
Could someone explain my mistake?
Your definition of xs is recursive, that is you're using xs inside its own definition. I don't think that's what you intended.
Since you're using "bang" and "boom" inside the list comprehensions, Haskell knows that xs must be a list of strings (because xs is equal to the result of the list comprehension). Further you say that x is an element of xs (x <- xs), so x must be a String (a.k.a. [Char]). However you do x < 3, which implies that x is a number. The error message means "a String is not a number".
Try to give the expression a type.
xs = [if x < 3 then "bang" else "boom" | x <- xs]
So xs is a list, we don't know yet what type its elements have, so let's look at that next. The list elements are
if x < 3 then "bang" else "boom"
which is an expression of type String (aka [Char]).
So xs :: [String]. Since the x from the expression describing the list elements is taken from the list xs itself, it is a String too, and is used in the comparison
if x < 3
Now, 3 is an integer literal, thus it is polymorphic and has type
3 :: Num a => a
So from the expression x < 3, we have
a Num constraint from the literal,
the type String from the fact that x is drawn from a list of Strings.
Thus we need a Num instance for String to have a well-typed expression.
Usually, there is no Num instance for String (what would a useful one look like?), so you get a type error.
If xs is the argument of a function,
boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
there is no reason why the type of x should be String, hence that works.
let xs = ...
means xs equals a list of "bang"s and/or "boom"s, but the condition states that those elements should be tested for <3, which is usually done with numbers, not strings.
let boom xs =...
equates the function 'boom' with the right hand side of the equation, where the parameter 'xs' is the list from which the elements to be tested for <3 are drawn.
Related
I'm learning Haskell and have some problems with list comprehension.
If I define a function to get a list of the divisors of a given number, I get an error.
check n = [x | x <- [1..(floor (n/2))], mod n x == 0]
I don't get why it's causing an error. If I want to generate a list from 1 to n/2 I can do it with [1..(floor (n/2))], but not if I do it in the list comprehension.
I tried another way but I get also an error (in this code I want to get all so called "perfect numbers")
f n = [1..(floor (n/2))]
main = print $ filter (\t -> foldr (+) 0 (f t) == t) [2..100]
Usually it is better to start writing a signature. While signatures are often not required, it makes it easier to debug a single function.
The signature of your check function is:
check :: (RealFrac a, Integral a) => a -> [a]
The type of input (and output) a thus needs to be both a RealFrac and an Integral. While technically speaking we can make such type, it does not make much sense.
The reason this happens is because of the use of mod :: Integral a => a -> a -> a this requires x and n to be both of the same type, and a should be a member of the Integral typeclass.
Another problem is the use of n/2, since (/) :: Fractional a => a -> a -> a requires that n and 2 have the same type as n / 2, and n should also be of a type that is a member of Fractional. To make matters even worse, we use floor :: (RealFrac a, Integral b) => a -> b which enforces that n (and thus x as well) have a type that is a member of the RealFrac typeclass.
We can prevent the Fractional and RealFrac type constaints by making use of div :: Integral a => a -> a -> a instead. Since mod already required n to have a type that is a member of the Integral typeclass, this thus will not restrict the types further:
check n = [x | x <- [1 .. div n 2], mod n x == 0]
This for example prints:
Prelude> print (check 5)
[1]
Prelude> print (check 17)
[1]
Prelude> print (check 18)
[1,2,3,6,9]
I am learning Haskell and recursion and different types in Haskell is making my brain hurt. I am trying to create a recursive function that will take a 32 bit binary number string and convert it to a decimal number. I think my idea for how the recursion will work is fine but implementing it into Haskell is giving me headaches. This is what I have so far:
bin2dec :: String -> Int
bin2dec xs = ""
bin2dec (x:xs) = bin2dec xs + 2^(length xs) * x
The function is supposed to take a 32 bit number string and then take off the first character of the string. For example, "0100101010100101" becomes "0" and "100101010100101". It then should turn the first character into a integer and multiply it by 2^length of the rest of the string and add it to the function call again. So if the first character in the 32 bit string is "1" then it becomes 1 * 2^(31) + recursive function call.
But, whenever I try to compile it, it returns:
traceProcP1.hs:47:14: error:
* Couldn't match type `[Char]' with `Int'
Expected: Int
Actual: String
* In the expression: ""
In an equation for `bin2dec': bin2dec xs = ""
|
47 | bin2dec xs = ""
| ^^
traceProcP1.hs:48:31: error:
* Couldn't match expected type `Int' with actual type `Char'
* In the second argument of `(+)', namely `2 ^ (length xs) * x'
In the expression: bin2dec xs + 2 ^ (length xs) * x
In an equation for `bin2dec':
bin2dec (x : xs) = bin2dec xs + 2 ^ (length xs) * x
|
48 | bin2dec (x:xs) = bin2dec xs + 2^(length xs) * x
| ^^^^^^^^^^^^^^^^^^
I know this has to do with changing the datatypes, but I am having trouble type casting in Haskell. I have tried type casting x with read and I have tried making guards that will turn the '0' into 0 and '1' into 1, but I am having trouble getting these to work. Any help would be very appreciated.
There is no casting. If you want to convert from one type to another, there needs to be a function with the right type signature to do so. When looking for any function in Haskell, Hoogle is often a good start. In this case, you're looking for Char -> Int, which has several promising options. The first one I see is digitToInt, which sounds about right for you.
But if you'd rather do it yourself, it's quite easy to write a function with the desired behavior, using pattern matching:
bit :: Char -> Int
bit '0' = 0
bit '1' = 1
bit c = error $ "Invalid digit '" ++ [c] ++ "'"
So I'd like to define a function (we'll call it applied) that would get rid of all occurrences of a sub-multiset within another multiset and replace each occurrence with a single element. For example,
applied {#a,a,c,a,a,c#} ({#a,a,c#}, f) = {#f,f#}
So at first I tried a definition:
definition applied :: "['a multiset, ('a multiset × 'a)] ⇒ 'a multiset" where
"applied ms t = (if (fst t) ⊆# ms then plus (ms - (fst t)) {#snd t#} else ms)"
However, I quickly realised that this would only remove one occurrence of the subset. So if we went by the previous example, we would have
applied {#a,a,c,a,a,c#} ({#a,a,c#}, f) = {#f,a,a,c#}
which is not ideal.
I then tried using a function (I initially tried primrec, and fun, but the former didn't like the structure of the inputs and fun couldn't prove that the function terminates.)
function applied :: "['a multiset, ('a multiset × 'a)] ⇒ 'a multiset" where
"applied ms t = (if (fst t) ⊆# ms then applied (plus (ms - (fst t)) {#snd t#}) t else ms)"
by auto
termination by (*Not sure what to put here...*)
Unfortunately, I can't seem to prove the termination of this function. I've tried using "termination", auto, fastforce, force, etc and even sledgehammer but I can't seem to find a proof for this function to work.
Could I please have some help with this problem?
Defining it recursively like this is indeed a bit tricky because termination is not guaranteed. What if fst t = {# snd t #}, or more generally snd t ∈# fst t? Then your function keeps running in circles and never terminates.
The easiest way, in my opinion, would be a non-recursive definition that does a ‘one-off’ replacement:
definition applied :: "'a multiset ⇒ 'a multiset ⇒ 'a ⇒ 'a multiset" where
"applied ms xs y =
(let n = Inf ((λx. count ms x div count xs x) ` set_mset xs)
in ms - repeat_mset n xs + replicate_mset n y)"
I changed the tupled argument to a curried one because this is more usable for proofs in practice, in my experience – but tupled would of course work as well.
n is the number of times that xs occurs in the ms. You can look at what the other functions do by inspecting their definitions.
One could also be a bit more explicit about n and write it like this:
definition applied :: "'a multiset ⇒ 'a multiset ⇒ 'a ⇒ 'a multiset" where
"applied ms xs y =
(let n = Sup {n. repeat_mset n xs ⊆# ms}
in ms - repeat_mset n xs + replicate_mset n y)"
The drawback is that this definition is not executable anymore – but the two should be easy to prove equivalent.
I am trying to implement a function here which takes a list of Bool representing binary numbers such as [True, False, False] and convert that into corresponding decimal number according to Horners method.
Function type would be [Bool] -> Int.
Algorithms which i am following is:
Horners Algorithm Visual Explanation:
So far i have implemented the logic in which it says first it will check whether the list is empty or either one element in the list [True], will give 1 and [False] will give 0.
Then in this case binToDecList (x:xs) = binToDecList' x 0 what i did to treat first element whether this is True or False.
binToDecList :: [Bool] -> Int
binToDecList [] = error "Empty List"
binToDecList [True] = 1
binToDecList [False] = 0
binToDecList (x:xs) = binToDecList' x 0
binToDecList' x d | x == True = mul (add d 1)
| otherwise = mul (add d 0)
add :: Int -> Int -> Int
add x y = x + y
mul :: Int -> Int
mul x = x * 2
I want to use the result of binToDecList' in the next iteration calling itself recursively on the next element of the list. How can i store the result and then apply it to next element of the list recursively. Any kind of help would be appreciated.
The type* of foldl tells us how it must work.
foldl :: (b -> a -> b) -> b -> [a] -> b
Clearly [a], the third argument that is a list of something, must be the list of Bool to be handed to Horner’s algorithm. That means the type variable a must be Bool.
The type variable b represents a possibly distinct type. We are trying to convert [Bool] to Int, so Int is a decent guess for b.
foldl works by chewing through a list from the left (i.e., starting with its head) and somehow combining the result so far with the next element from the list. The second argument is typically named z for “zero” or the seed value for the folding process. When foldl reaches the end of the list, it returns the accumulated value.
We can see syntactically that the first argument is some function that performs some operation on items of type b and type a to yield a b. Now, a function that ignores the a item and unconditionally results in whatever the b is would fit but wouldn’t be very interesting.
Think about how Horner’s algorithm proceeds. The numbers at the elbows of the path on your diagram represent the notional “result so far” from the previous paragraph. We know that b is Int and a is Bool, so the function passed to foldl must convert the Bool to Int and combine it with the result.
The first step in Horner’s algorithm seems to be a special case that needs to be handled differently, but foldl uses the same function all the way through. If you imagine “priming the pump” with an invisible horizontal move (i.e., multiplying by two) to begin with, we can make the types fit together like puzzle pieces. It’s fine because two times zero is still zero.
Thus, in terms of foldl, Horner’s algorithm is
horners :: [Bool] -> Int
horners = foldl f 0
where f x b =
let b' = fromEnum b
in 2*x + b'
Notice that 2*x + b' combines subsequent horizontal and vertical moves.
This also suggests how to express it in direct recursion.
horners' :: [Bool] -> Int
horners' [] = 0
horners' l = go 0 l
where -- over then down
go x [] = x
go x (b:bs) =
let b' = fromEnum b
in go (2*x + b') bs
Here the inner go loop is performing the left-fold and combining each next Bool with the result so far in i.
* A pedagogical simplification: the actual type generalizes the list type into Foldable.
I'm learning Haskell and I'm trying to write a function to return a list of factors for a number. Here's what I have:
factors :: Int -> [Int]
factors n = [x | x <- [2..s], n `mod` x == 0]
where s = floor (sqrt n)
When I try to load the module in ghci, I get two errors,
p003.hs:3:14:
No instance for (RealFrac Int)
arising from a use of `floor' at p003.hs:3:14-27
Possible fix: add an instance declaration for (RealFrac Int)
In the expression: floor (sqrt n)
In the definition of `s': s = floor (sqrt n)
In the definition of `factors':
factors n = [x | x <- [2 .. s], n `mod` x == 0]
where
s = floor (sqrt n)
p003.hs:3:21:
No instance for (Floating Int)
arising from a use of `sqrt' at p003.hs:3:21-26
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `floor', namely `(sqrt n)'
In the expression: floor (sqrt n)
In the definition of `s': s = floor (sqrt n)
Failed, modules loaded: none.
Any suggestions?
The parameter has type Int, so you cannot calculate a square root for it. You need to convert it to a floating point type first, which you can do with fromIntegral. Unlike some other languages, Haskell does not automatically promote integers to floating point numbers (nor do any other automatic type conversions).
So change sqrt n to sqrt (fromIntegral n).
The cause of the problem
The type of the sqrt function is
sqrt :: (Floating a) => a -> a
You can check this by typing :t sqrt in ghci.
Int is not an instance of Floating, which is why you're seeing the second error.
The cause of the first error is the same; checking :t floor reveals that the type is:
floor :: (RealFrac a, Integral b) => a -> b
The function is expecting an instance of RealFrac, and you're supplying an Int.
Typing :info RealFrac or :info Floating reveals that neither has an instance for Int, which is why the body of the error says
No instance for ... Int
The solution
The solution to this problem, is to make sure that the types are correct; they must be members of the proper type classes.
A simple way to do this is to use the fromIntegral function, which :t reveals is of type:
fromIntegral :: (Integral a, Num b) => a -> b
Using fromIntegral is necessary because the incoming type is Int, but the functions floor and sqrt operate on types RealFrac and Floating, respectively.
It's allowed because, as you can see from the type signature, fromIntegral returns an instance of Num, which includes both the RealFrac and Floating types. You can convince yourself of this by typing :info Num and :info Float into ghci, and viewing the output.
Making his change to your program would have the final result below, which should work as you want:
factors :: Int -> [Int]
factors n = [x | x <- [2..s], n `mod` x == 0]
where s = floor (sqrt $ fromIntegral n)
Further reading
Two good resources for understanding exactly what's going on are the Haskell tutorial's sections on Type Classes and Numbers.