Lambda abstraction pattern matching in haskell - 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.

Related

mapping multiple functions in haskell

I'm working on a way of representing memory in Haskell that looks like this...
data MemVal = Stored Value | Unbound
deriving Show
type Memory = ([Ide],Ide -> MemVal)
As an Identifier is called its added to the list of Identifiers. If an error occurs in the program I want to be able to recall the identifiers used up to date. So far I have this...
display :: Memory -> String
display m = "Memory = " ++ show (map (snd m) (fst m)) ++ " "
But was wondering if there were a way to map the name of the identifier to (fst m) as well as the function (snd m) so the output will be similar to...
Memory = [sum = stored Numeric 1, x = stored Boolean true]
Thank you.
You probably want something like this
display :: Memory -> String
display (ides, mem) =
"Memory = [" ++ unwords (map (\x -> x ++ "=" ++ mem x) ides) ++ "]"
I'm guessing this is what you are after:
import Data.List (intercalate)
display (Memory ids f) = "Memory = [" ++ (intercalates ", " assigns) ++ "]"
where assigns = [ show i ++ " = " ++ show (f i) | i <- ids ]
Here assigns is a list like:
[ "sum = stored Numeric 1", "x = stored Boolean true", ...]
and intercalate ", " assigns joins the strings together.
I've used destructuring to avoid having to refer to fst ... and snd ...

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

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"

Haskell non-exhaustive patterns and converting function output

I have a function that wants to list all of a dataType.
fn [] = []
fn (dt#(DataType t d y [(f,r)]):dts) = ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)] ++ fn dts
Where t and d are strings, y is an int, f is a string and r is an int (not sure f and r matter though, will explain furthur on).
I got the error non-exhaustive patterns, and presumed it was because I didn't have one for when there was only one element in the list, so I added this between the other patterns:
fn [dt#(DataType t d y [(f,r)])] = ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)]
It compiled, but when I called the function it once again told me 'non-exhaustive patterns'. I'm struggling to think of what pattern i've missed, should I add a wildcard pattern afterward to catch everything? I'm not looking for someone to type out the answer, but hints or suggestions are welcome.
The pattern [(f,r)] only matches when the list contains one element. If it contains zero, or two, or any other number, you have a pattern match failure.
What the code should do in this instance, I couldn't say...
You do already cover the one-element-list case: that matches fn (dt#(DataType t d y [(f,r)]):[]), since dts can be anything including the empty list.
Indeed there's no reason to use explicit recursion here: you basically have something like
f [] = []
f (x:xs) = g x ++ f xs
Compare that to the monad instance of lists:
instance Monad [] where
return x = [x]
[] >>= _ = []
(x:xs) >>= g = g x ++ (xs >>= g)
So you should write you function as
fn l = l >>= \dt#( DataType t d y [(f,r)] )
-> ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)]
That won't fix your problem though, but it makes it obvious what's going on: evidently, DataType t d y [(f,r)] is not the only valid pattern for that type. As MathematicalOrchid points out, [(f,r)] matches only a list with length 1, but you need to cover other lengths as well.
fn l = l >>= \dt -> case dt of
DataType t d y [(f,r)]
-> ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)]
DataType t d y []
-> ["Some other stuff"]
DataType t d y [(f,r), ...]
-> ["Yet other stuff"]
or whatever.
Indeed, if you only ever return [ ("stuff") ] here, then you're not really using the monadic bind functionality at all: you could have written the recursive version without ++, only reconstruct the thing with :, and in fact you have simply a map operation:
fn = map $ \dt -> case dt of
DataType t d y [(f,r)]
-> "T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)
DataType t d y []
-> "Some other stuff"
DataType t d y [(f,r), ...]
-> "Yet other stuff"

Better display of boolean formulas

I want to implement a method for showing a propositional formula in SML. The solutions that I found so far was of this type:
fun show (Atom a) = a
| show (Neg p) = "(~ " ^ show p ^ ")"
| show (Conj(p,q)) = "(" ^ show p ^ " & " ^ show q ^ ")"
| show (Disj(p,q)) = "(" ^ show p ^ " | " ^ show q ^ ")";
This produces unnecessary braces:
((~p) & (q | r))
when, what I'd like to have is:
~ p & (q | r)
I saw, that Haskell has a function (display?) which does this nicely. Can someone help me out a little bit. How should I go about this?
If you want to eliminate redundant parentheses, you will need to pass around some precedence information. For example, in Haskell, the showsPrec function embodies this pattern; it has type
showsPrec :: Show a => Int -> a -> String -> String
where the first Int argument is the precedence of the current printing context. The extra String argument is a trick to get efficient list appending. I'll demonstrate how to write a similar function for your type, though admittedly in Haskell (since I know that language best) and without using the extra efficiency trick.
The idea is to first build a string that has no top-level parentheses -- but does have all the parentheses needed to disambiguate subterms -- then add parentheses only if necessary. The unbracketed computation below does the first step. Then the only question is: when should we put parentheses around our term? Well, the answer to that is that things should be parenthesized when a low-precedence term is an argument to a high-precedence operator. So we need to compare the precedence of our immediate "parent" -- called dCntxt in the code below -- to the precedence of the term we're currently rendering -- called dHere in the code below. The bracket function below either adds parentheses or leaves the string alone based on the result of this comparison.
data Formula
= Atom String
| Neg Formula
| Conj Formula Formula
| Disj Formula Formula
precedence :: Formula -> Int
precedence Atom{} = 4
precedence Neg {} = 3
precedence Conj{} = 2
precedence Disj{} = 1
displayPrec :: Int -> Formula -> String
displayPrec dCntxt f = bracket unbracketed where
dHere = precedence f
recurse = displayPrec dHere
unbracketed = case f of
Atom s -> s
Neg p -> "~ " ++ recurse p
Conj p q -> recurse p ++ " & " ++ recurse q
Disj p q -> recurse p ++ " | " ++ recurse q
bracket
| dCntxt > dHere = \s -> "(" ++ s ++ ")"
| otherwise = id
display :: Formula -> String
display = displayPrec 0
Here's how it looks in action.
*Main> display (Neg (Conj (Disj (Conj (Atom "a") (Atom "b")) (Atom "c")) (Conj (Atom "d") (Atom "e"))))
"~ ((a & b | c) & d & e)"

Printing in Haskell

I have a function that returns Floats (or some other type). I am using my program as a module in ghci. How would I print out info at certain points in the program? For example, if I detect bad input to a function, how do I print out an error message?
There are a few cases here, depending on what you want to do.
The straight forward sprinkling of printfs as a method of debugging is not going to work very well in Haskell.
If you have a partial function, I would suggest using Either or Maybe as a solution.
For example:
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup x [] = Nothing
lookup x ((k,v):ys) | x == k = Just v
| otherwise = lookup x ys
lookup takes a key, and a list of key-value pairs and return Just the value associated with that key, or Nothing if the key is not in the list.
doMath :: Char -> Int -> Int -> Either String Int
doMath '+' x y = Right (x + y)
doMath '*' x y = Right (x * y)
doMath '/' x 0 = Left "Division by zero"
doMath '/' x y = Right (x / y)
doMath '-' x y = Right (x - y)
doMath c x y = Left ("Bad operator: " ++ show c)
Either is like maybe, in that if you can, you will return the right result. Otherwise you take what's left.
If your function really has an impossible case, then you can use the function error, which throws a pretty much uncatchable error with a string. It's not pretty, but it will help point you in the right direction when doing a post-mortem after the impossible does happen.
Because there are no side effects in pure code, you basically have three options:
You can print an error message and throw an exception, which usually terminates the program unless you catch it:
myDiv x 0 = error "Division by zero"
myDiv x y = x / y
You can print an error message and return some value:
import Debug.Trace
myDiv x y = trace ("Trying to divide " ++ show x ++ " by " ++ show y) (x / y)
You can return a value which describes the error in some way, e.g. Maybe or Either String:
myDivMaybe x 0 = Nothing
myDivMaybe x y = Just (x / y)
myDivEither x 0 = Left "Won't divide by zero"
myDivEither x y = Right (x / y)
You usually use error when the input is really invalid and you don't mind a runtime error in that case. trace is usually used for debugging purposes. If you want to avoid runtime errors on invalid input, you can use Maybe or Either.

Resources