Why does the Haskell `show ` function give me trouble here? - haskell

I am just a few days into Haskell and learning it from Learn You a Haskell for a great good. While trying out one of the 99 Haskell problems, I ran into the following error while loading my function into ghci.
The problem asks to write a function elementAt k x which takes a number k, a list x and extracts the kth element of the list x.
Here is my function
elementAt :: Int -> [a] -> a
elementAt k x
| k < 0 = error "You have passed a negative index"
| null x = error "Cannot extract from an empty list"
| (length x) < k = error "The array contains fewer than " ++ (show k) ++ "elements"
elementAt 0 (x:_) = x
elementAt k (_:xs) = elementAt (k-1) xs
On loading this function into ghci I get the error
Couldn't match expected type `a' with actual type `[Char]'
`a' is a rigid type variable bound by
the type signature for elementAt :: Int -> [a] -> a at fun.hs:77:14
Relevant bindings include
x :: [a] (bound at fun.hs:78:13)
elementAt :: Int -> [a] -> a (bound at fun.hs:78:1)
In the expression:
error "The array contains fewer than " ++ (show k) ++ "elements"
In an equation for `elementAt':
elementAt k x
| k < 0 = error "You have passed a negative index"
| null x = error "Cannot extract from an empty list"
| (length x) < k
= error "The array contains fewer than " ++ (show k) ++ "elements"
The trouble seems to lie with the way I have used the show function, but I
don't see why. On removing the show call the function seems to compile and
work perfectly.

You will need to put parentheses around your error message in line 5.
Currently your implementation is equal to this one:
(error "The array contains fewer than ") ++ show k ++ "elements"
While you most likely wanted it to do this:
error ("The array contains fewer than " ++ show k ++ "elements")
You can also use the ($) syntax like so:
error $ "The array contains fewer than " ++ show k ++ "elements"

According to Haskell Report, f x ++ g y parses as (f x) ++ (g y). In your case,
error "The array contains fewer than " ++ (show k) ++ "elements"
parses as
(error "The array contains fewer than ") ++ (show k) ++ "elements"

Related

Lambda abstraction pattern matching in haskell

I am trying to write a function which outputs all variable names. When used on the example below, the output should be
*Main> used example
["a","b","x","y"]
This is what I have written so far...
import Data.Char
import Data.List
type Var = String
data Term =
Variable Var
| Lambda Var Term
| Apply Term Term
-- deriving Show
instance Show Term where
show = pretty
example :: Term
example = Lambda "a" (Lambda "x" (Apply (Apply (Lambda "y" (Variable "a")) (Variable "x")) (Variable "b")))
pretty :: Term -> String
pretty = f 0
where
f i (Variable x) = x
f i (Lambda x m) = if i /= 0 then "(" ++ s ++ ")" else s where s = "\\" ++ x ++ ". " ++ f 0 m
f i (Apply n m) = if i == 2 then "(" ++ s ++ ")" else s where s = f 1 n ++ " " ++ f 2 m
used :: Term -> [Var]
used (Variable n) = [n]
used (Lambda n t) = "\\" ++ n ++ ". " ++ used t
used (Apply t1 t2) = used t1 ++ used t2
The problem lies in the line used (Lambda n t) = "\\" ++ n ++ ". " ++ used t, I get this error message:
list.hs:28:47: error:
lexical error in string/character literal at character '\n'
|
28 | used (Lambda n t) = "\" ++ n ++ ". " ++ used t
Why am I getting this complaint?
You are copying and pasting from examples too much. Keep thinking about what the function is supposed to mean as you are writing it.
used (Variable n) = [n]
This is correct: the set of variables used in a term which is just a variable is the variable used. For example, the set of variables used in the term x is just [x].
used (Apply t1 t2) = used t1 ++ used t2
This is also correct1: the set of variables used in say (x y z) (w x y) is the union of the variables used in x y z and in w x y: that is [x,y,z,w,x,y].
So now let's consider the case you are struggling with.
used (Lambda n t) = ...
The code you have seems to be attempting to print the the term into a string, which is not what we are trying to do here -- we are trying to find the set of used variables.
Let's consider an example: we have a term like (\x. x y z), and we want to find out what its used variables are. Before trying to come up with the general solution, ask yourself what the result should be in this example.
If this function is going to be nicely recursive, can we express your expected result in terms of the used variables of x y z? How do we transform the set of used variables of x y z into the set of used variables of \x. x y z?
1 Though you might get duplicates.

Variable not in scope error in function using guards

I am trying to print a linked list in Haskell using the following code:
data List = Node {value:: Double, next:: List}
| Empty
printList :: List -> String
printList x | x == (Node v n) = show v ++ " " ++ printList n
| otherwise = show '_'
And getting the compilation error:
:load scratch.hs
[1 of 1] Compiling Main ( scratch.hs, interpreted )
scratch.hs:5:26: error: Variable not in scope: v :: Double
scratch.hs:5:28: error: Variable not in scope: n :: List
scratch.hs:5:38: error: Variable not in scope: v
scratch.hs:5:53: error: Variable not in scope: n :: List
Failed, modules loaded: none.
While I'm able to do the same using pattern matching without guards.
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = ""
What's wrong with the first code?
You do not do pattern matching by using an equality check: it is possible that two different patterns are considered equal.
So what you can do is define a pattern in the head of one of the clauses of your function. For instance:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'
So now Haskell will, for a given List check if it matches with the Node v n pattern, and if so unpack the element and assign the head to v and the tail to n.
We can however still improve the code. Usually you better do not use wildcard patterns, but use all possible patterns. Since if you later want to alter the definition of List, the compiler can give you a warning that you forgot a pattern:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = show '_'
Another thing we can improve is using "_" over show '_'. Since show '_' will add quotes to the content. For instance:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
Finally we can also use a "cons" construction over appending with a singleton list:
printList :: List -> String
printList (Node v n) = show v ++ ' ' : printList n
printList Empty = "_"

Haskell: Exception <<loop>> on recursive data entry

So I'm trying to make a little program that can take in data captured during an experiment, and for the most part I think I've figured out how to recursively take in data until the user signals there is no more, however upon termination of data taking haskell throws Exception: <<loop>> and I can't really figure out why. Here's the code:
readData :: (Num a, Read a) => [Point a] -> IO [Point a]
readData l = do putStr "Enter Point (x,y,<e>) or (d)one: "
entered <- getLine
if (entered == "d" || entered == "done")
then return l
else do let l = addPoint l entered
nl <- readData l
return nl
addPoint :: (Num a, Read a) => [Point a] -> String -> [Point a]
addPoint l s = l ++ [Point (dataList !! 0) (dataList !! 1) (dataList !! 2)]
where dataList = (map read $ checkInputData . splitOn "," $ s) :: (Read a) => [a]
checkInputData :: [String] -> [String]
checkInputData xs
| length xs < 2 = ["0","0","0"]
| length xs < 3 = (xs ++ ["0"])
| length xs == 3 = xs
| length xs > 3 = ["0","0","0"]
As far as I can tell, the exception is indication that there is an infinite loop somewhere, but I can't figure out why this is occurring. As far as I can tell when "done" is entered the current level should simply return l, the list it's given, which should then cascade up the previous iterations of the function.
Thanks for any help. (And yes, checkInputData will have proper error handling once I figure out how to do that.)
<<loop>> basically means GHC has detected an infinite loop caused by a value which depends immediately on itself (cf. this question, or this one for further technical details if you are curious). In this case, that is triggered by:
else do let l = addPoint l entered
This definition, which shadows the l you passed as an argument, defines l in terms of itself. You meant to write something like...
else do let l' = addPoint l entered
... which defines a new value, l', in terms of the original l.
As Carl points out, turning on -Wall (e.g. by passing it to GHC at the command line, or with :set -Wall in GHCi) would make GHC warn you about the shadowing:
<interactive>:171:33: warning: [-Wname-shadowing]
This binding for ‘l’ shadows the existing binding
bound at <interactive>:167:10
Also, as hightlighted by dfeuer, the whole do-block in the else branch can be replaced by:
readData (addPoint l entered)
As an unrelated suggestion, in this case it is a good idea to replace your uses of length and (!!) with pattern matching. For instance, checkInputData can be written as:
checkInputData :: [String] -> [String]
checkInputData xs = case xs of
[_,_] -> xs ++ ["0"]
[_,_,_] -> xs
_ -> ["0","0","0"]
addPoint, in its turn, might become:
addPoint :: (Num a, Read a) => [Point a] -> String -> [Point a]
addPoint l s = l ++ [Point x y z]
where [x,y,z] = (map read $ checkInputData . splitOn "," $ s) :: (Read a) => [a]
That becomes even neater if you change checkInputData so that it returns a (String, String, String) triple, which would better express the invariant that you are reading exactly three values.

error Couldn't match expected type ‘Char’ with actual type ‘[Char]’

I am trying to build a string representation for the show function of a typeclass representing a polynomial. I keep getting type errors of a mismatch from 'Char' to '[Char]', but from my understanding haskell's "append" function should be able to concatenate a Char to a string/[Char]. I don't understand where the problem lies, or where to look for a solution based on the errors I receive. here is the faulty code:
newtype Poly a = P [a]
instance (Num a, Show a) => Show (Poly a) where
show p = ["" : form (p !! i) i | i <- [l,(l-1)..0]]
where
l = length p
form e i
| i == 0 = elem
| i == 1 = elem ++ "x + "
| otherwise = elem ++ "x^" ++ (show i) ++ " + "
where elem = show e
any help would be greatly appreciated, thanks in advance.
You write
from my understanding haskell's "append" function should be able to concatenate a Char to a string/[Char].
I have no idea where you got this idea. It's wrong. I'm guessing you've defined
type Poly a = [a]
and I'll go with that assumption.
instance (Num a, Show a) => Show (Poly a) where
This is wrong. Poly is a type synonym. You can only declare instances for proper first-class types (the application of a type constructor to zero or more type variables). You can fix this by using, instead,
newtype Poly a = Poly {getPoly :: [a]}
but then you need to wrap/unwrap the Poly data constructor as required. Once you've gotten this right, you'll probably see that the Num constraint you've given is unnecessary.
show p = ["" ++ form (p !! i) i | i <- [(length p)..0]]
There are a few problems. The big one is that this does not define a string (list of characters) but rather a list of strings. You can fix this, generally, by applying concat to the result. The second one is that "" ++ anything is just anything, because concatenating the empty list to another list doesn't do anything. The third problem is that you're trying to count down, but you've done it wrong. That notation only counts up. To count down, you have to show that you want to count down:
let lp = length p in [lp, (lp-1) .. 0]
The last thing I see immediately (some of these mistakes are repeated in the preceding two lines):
| otherwise = e ++ "x^" ++ i ++ " + "
Now i is an Int, and ++ only works for lists. So that will not work. You need to first convert i to a string using show. e is of type a, and needs to be converted to a string using show as well.

Functional Purity using 'let' in Haskell

As I am working on learning Haskell, I understand it is a purely functional language. I am having trouble understanding why let-statements don't violate purity.
For example (in ghci):
Prelude> let e = exp 1
Prelude> e
2.718281828459045
Prelude> let e = 2
Prelude> e
2
isn't my second let statement producing a side effect? Or is the second let statement a new closure?
Your second let creates a new binding for e that shadows the existing variable. It does not modify e. You can easily check this with the following:
Prelude> let e = 1
Prelude> let f () = "e is now " ++ show e
Prelude> f ()
"e is now 1"
Prelude> let e = 2
Prelude> e
2
Prelude> f ()
"e is now 1"
Prelude>
let introduces a new local variable with a single unalterable value, and it has more local scope than any surrounding definitions, so for example:
*Main> (let length = 2 in show length) ++ ' ':show (length "Hello")
"2 5"
Here the first length has the value 2, but its scope local to the brackets. Outside the brackets, length means what it has always meant. Nothing has been edited, just a more local variable has been introduced that happens to have the same name as another one in a different scope. Let's make ghci mad by omitting the brackets and making it try to make length a number and a function:
*Main> let length = 2 in show length ++ ' ':show (length "Hello")
<interactive>:1:14:
No instance for (Num ([Char] -> a0))
arising from the literal `2'
Possible fix: add an instance declaration for (Num ([Char] -> a0))
In the expression: 2
In an equation for `length': length = 2
In the expression:
let length = 2 in show length ++ ' ' : show (length "Hello")
<interactive>:1:19:
No instance for (Show ([Char] -> a0))
arising from a use of `show'
Possible fix: add an instance declaration for (Show ([Char] -> a0))
In the first argument of `(++)', namely `show length'
In the expression: show length ++ ' ' : show (length "Hello")
In the expression:
let length = 2 in show length ++ ' ' : show (length "Hello")
And here's your example:
*Main> let e = exp 1 in show e ++ " " ++ let e = 2 in show e
"2.718281828459045 2"
I'll add brackets to emphasise the scope:
*Main> let e = exp 1 in (show e ++ " " ++ (let e = 2 in (show e)))
"2.718281828459045 2"
The first e is hidden rather than edited. Referential transparency is preserved, but it's definitely bad practice because it's hard to follow.
Now secretly the interactive prompt is a bit like one big do block in the IO monad, so let's look at that:
testdo = do
let e = exp 1
print e
let e = 2
print e
Now I have to admit that looks an awful lot like breaking referential transparency, but bear in mind that this looks like it does too:
testWrite = do
writeFile "test.txt" "Hello Mum"
xs <- readFile "test.txt"
print xs
writeFile "test.txt" "Yo all"
xs <- readFile "test.txt"
print xs
Now in what sense have we got referential transparency? xs clearly refers to two different strings. Well, what does this do notation actually mean? It's syntactic sugar for
testWrite = writeFile "test.txt" "Hello Mum"
>> readFile "test.txt"
>>= (\xs -> print xs
>> writeFile "test.txt" "Yo all"
>> readFile "test.txt"
>>= (\xs -> print xs))
Now it's clearer that what looks like assignment is just local scope again. You presumably are happy to do
increment :: [Int] -> [Int]
increment = \x -> map (\x -> x+1) x
Which is doing the same thing.
Summary
What appeared to be assignment is just introduction of a new local scope. Phew. If you use this a lot, you make it very unclear what your code means.

Resources