So, I have already defined the lambda data type as such:
data LExpr
= Variable String -- variable
| Apply LExpr LExpr -- function application
| Lambda String LExpr -- Lambda abstraction
deriving (Eq, Show)
Now I want to implement an instance of Show myself. I have already the function show' which does most of the work, but without using instances:
show' :: LExpr -> String
show' (Variable a) = a
show' (Apply e1 e2) = "(" ++ show' e1 ++ " " ++ show' e2 ++ ")"
show' (Lambda x e) = "(λ " ++ x ++ ". " ++ show' e ++ ")"
How I can implement it, to get the following output without using explicitly the show' function:
Main> (Apply (Lambda "x" (Apply (Variable "x") (Variable "y"))) (Variable "z"))
((λ x. x y) y)
Add an instance declaration for the Show class.
instance Show LExpr where
show = show'
And remove the deriving(Show) part
data LExpr
= Variable String -- variable
| Apply LExpr LExpr -- function application
| Lambda String LExpr -- Lambda abstraction
deriving (Eq)
Related
data Expr = Var Char | Not Expr | And Expr Expr | Or Expr Expr deriving (Eq, Ord)
instance Show Expr where
show (Var x) = [x]
show (Not (Var y)) = "~"++ show (Var y)
show (And (Var x) (Var y)) = show (Var x) ++ " ^ " ++ show (Var y)
show ((Or (Var x) (Var y))) = show (Var x) ++ " v " ++ show (Var y)
show (Not (Or (Var x) (Var y))) = "~(" ++ show (Or (Var x) (Var y)) ++ ")"
show (And (Var x) (And (Var y) (Var z))) = show (Var x) ++ " ^ " ++ "(" ++ show (And (Var y) (Var z)) ++ ")"
I`m not sure exactly why i get this error when i run:
>(Not (Not (Var 'a')))
*** Exception: (21,5)-(26,112): Non-exhaustive patterns in function show
Can anyone help me.
An And can also contain another And, so for example And (And (Var 'x') (Var 'y')) (Var 'z'). In your Show instance you always assume that the parameters are Vars, that is not necessary.
You can implement the Show instance as:
instance Show Expr where
show (Var x) = [x]
show (Not x) = "~ ("++ show x ++ ")"
show (And x y) = "(" ++ show x ++ " ^ " ++ show y ++ ")"
show (Or x y) = "(" ++ show x ++ " v " ++ show y ++ ")"
This will introduce a lot of parenthesis. Therefore it is better to work with a precedence parameter. In fact the Show instance already has support for this: you can work with showsPrec :: Int -> a -> String -> String. Here the Int parameter is the operator precedence of the outer context, and the first String parameter is the string that needs to be appended at the end: that is done for performance reasons.
We thus can implement this as:
instance Show Expr where
showsPrec n (Var x) = (x :)
showsPrec n (Not x) = showParen (n > 9) ( ('~' :) . showsPrec 10 x)
showsPrec n (And x y) = showParen (n > 8) ((showsPrec 9 x) . (" ^ " ++) . showsPrec 9 y)
showsPrec n (Or x y) = showParen (n > 7) ((showsPrec 8 x) . (" v " ++) . showsPrec 8 y)
Here we will show parenthesis for not if the outer countext has a precedence higher than 9, and call the showPrec with a precence 10 such that the showPrec inside will not print extra parenthesis, unless it has a precedence of 10 or higher. The same applies for the other functions.
This thus means that we can print an expression with parenthesis like:
ghci> show (Not (And (Or (Not (Var 'x')) (Var 'y')) (Var 'z')))
"~((~x v y) ^ z)"
Here the And … … will thus print parenthesis since it is called with a precedence of nine, and the threshold is 8 to print parenthesis. But there are no brackets for around ~x, since the threshold is lower than 10.
Instead of hard-coding lots of deep expressions, you should just pattern match on the topmost constructors and then recurse down.
instance Show Expr where
show (Var v) = [v]
show (Not x) = "Not ("++show x++")"
show (And x y) = "(" ++ show x ++ ") ∧ (" ++ ...
show (Or x y) = ...
Remember to implement the ∧ and ∨ operators if you mention them in the show results.
infixr 3 ∧
(∧) :: Expr -> Expr -> Expr
(∧) = And
Actually it is preferred to not implement show when defining recursive-data Show instances, instead implement showsPrec which has a more sophisticated way of adding parentheses as needed.
I have a data type and function like this:
data Expr = Num Int | Add Expr Expr | Mult Expr Expr | Neg Expr | If Expr Expr Expr deriving (Show, Read)
prettyPrint :: Expr -> IO ()
prettyPrint expr = prettyPrint' expr 0
prettyPrint' :: Expr -> Int -> IO ()
prettyPrint' (Num x) i = putStrLn $ concat (replicate i " ") ++ "Num " ++ show x
prettyPrint' (Add x y) i = do
putStrLn $ concat (replicate i " ") ++ "Add"
prettyPrint' x (i+1)
prettyPrint' y (i+1)
prettyPrint' (Mult x y) i = do
putStrLn $ concat (replicate i " ") ++ "Mult"
prettyPrint' x (i+1)
prettyPrint' y (i+1)
prettyPrint' (Neg x) i = do
putStrLn $ concat (replicate i " ") ++ "Neg"
prettyPrint' x (i+1)
prettyPrint' (If x y z) i = do
putStrLn $ concat (replicate i " ") ++ "If"
prettyPrint' x (i+1)
prettyPrint' y (i+1)
prettyPrint' z (i+1)
In the function I am using pattern matching. The problem is that their is a lot of reuse of code. For example, the case for Mult and Add is basically the same code. Same goes for Num and Neg. Is there a way to write this based on how many variables the expression have? Like one for Num and Neg, since they have only one variable. One case for Mult and Add, since they have two variables. And a last case for If, since that expression have three variables.
NOTE:
I landed on this answer, I think it's a better solution than I started with:
prettyPrint :: Expr -> IO ()
prettyPrint expr = putStrLn (prettyPrint' 1 expr)
prettyPrint' :: Int -> Expr -> String
prettyPrint' i (Num x) = "Num " ++ show x
prettyPrint' i expr =
let indent x = concat (replicate i " ") ++ x
(op, args) = case expr of
Add x y -> ("Add", [x,y])
Mult x y -> ("Mult", [x,y])
Neg x -> ("Neg", [x])
If x y z -> ("If", [x,y,z])
in intercalate "\n" (op : map (indent . prettyPrint' (i + 1)) args)
First, I would stay out of the IO monad for as long as possible. Have prettyPrint' return a string to be printed.
prettyPrint :: Expr -> IO ()
prettyPrint = putStrLn . prettyPrint'
Now, the only job of prettyPrint' is to create a (possibly multiline) string to be printed. For numbers, that's easy: just use the show instance.
prettyPrint' :: Expr -> String
prettyPrint' e#(Num _) = show e
-- or, ignoring the Show instance for Expr altogether
-- prettyPrint' (Num x) = "Num " ++ show x
For the rest, there is a pattern:
Identify the constructor
Identify its arguments
Join the constructor name and its pretty-printed arguments with newlines. Each argument will be indented one level relative to its operator; the recursion will take care of multiple levels of indentation.
That will look like
prettyPrint' expr = let indent x = " " ++ x
(op, args) = case expr of
Add x y -> ("Add", [x,y])
Mult x y -> ("Mult", [x,y])
Neg x -> ("Neg", [x])
If x y z -> ("If", [x,y,z])
in intercalate "\n" (op : map (indent . prettyPrint') args)
As an example, consider what prettyPrint' will do with the expression Add (Num 3) (Num 5). First, it sets op to "Add" and args to [Num 3, Num 5]. Next, it maps indent . prettyPrint' over the argument list, to get [" Num 3", " Num 5"]. Putting the operator on the front of the list yields ["Add", " Num 3", " Num 3"], then joining them with intercalate produces "Add\n Num 3\n Num 5".
The only remaining boilerplate is in the case expression. I think it's possible to eliminate that, but it requires a level of generic programming I'm not familiar with. I'm sure someone else could probably run with my answer to fix that.
In general, when addressing duplication in code, it pays to keep the rule of three in mind. Two occurrences of a block of code isn't necessarily a problem.
That said, Haskell is a (very) strongly-typed language, so you generally can't pattern-match on arity like you can in, say, Erlang or Clojure.
If you really want to abstract away the recursion part of a recursive data structure, you can define the catamorphism for it. People often also call this a fold, so let's keep that slightly more friendly name:
data Expr =
Num Int | Add Expr Expr | Mult Expr Expr | Neg Expr | If Bool Expr Expr deriving (Show, Read)
foldExpr ::
(Int -> a) -> (a -> a -> a) -> (a -> a -> a) -> (a -> a) -> (Bool -> a -> a -> a) -> Expr -> a
foldExpr num _ _ _ _ (Num x) = num x
foldExpr num add mul neg iff (Add x y) =
add (foldExpr num add mul neg iff x) (foldExpr num add mul neg iff y)
foldExpr num add mul neg iff (Mult x y) =
mul (foldExpr num add mul neg iff x) (foldExpr num add mul neg iff y)
foldExpr num add mul neg iff (Neg x) = neg (foldExpr num add mul neg iff x)
foldExpr num add mul neg iff (If b x y) =
iff b (foldExpr num add mul neg iff x) (foldExpr num add mul neg iff y)
This is an entirely generic function that enables you turn turn any Expr value into any value of the type a, without worrying about reimplementing recursion every time. You just have to supply functions that deal with each of the cases.
You can, for example, easily write an evaluator:
evaluate :: Expr -> Int
evaluate = foldExpr id (+) (*) negate (\p x y -> if p then x else y)
(Notice, BTW, that I changed the definition of If, because I couldn't see how the OP definition would work.)
You can also write a function to turn an Expr value into a string, although this one is just a sketch; it needs indentation or bracket logic to work correctly:
prettyPrint :: Expr -> String
prettyPrint =
foldExpr
show -- Num
(\x y -> x ++ "+" ++ y) -- Add
(\x y -> x ++ "*" ++ y) -- Mult
(\x -> "(-" ++ x ++ ")") -- Neg
(\p x y -> "if " ++ show p ++ " then " ++ x ++ " else " ++ y) -- If
You can try it out in GHCi:
*Q53284410> evaluate (Num 42)
42
*Q53284410> evaluate (Add (Num 40) (Num 2))
42
*Q53284410> evaluate (Add (Mult (Num 4) (Num 10)) (Num 2))
42
*Q53284410> prettyPrint $ Num 42
"42"
*Q53284410> prettyPrint $ Mult (Num 6) (Num 7)
"6*7"
*Q53284410> prettyPrint $ Add (Mult (Num 2) (Num 3)) (Num 7)
"2*3+7"
Yes, just create a function to print list of Expr:
import Control.Monad (forM_)
printExprList::[Expr]->Int->String->IO ()
printExprList exprs i desc = do
putStrLn $ concat (replicate i " ") ++ desc
forM_ (zip exprs [i..]) $ \(e, j)-> prettyPrint' e (j+1)
and then call it to print:
prettyPrint' :: Expr -> Int -> IO ()
prettyPrint' (Add x y) i = printExprList [x, y] i "Add"
prettyPrint' (Mult x y) i = printExprList [x, y] i "Mult"
prettyPrint' (Neg x) i = printExprList [x] i "Neg"
prettyPrint' (If x y z) i = printExprList [x, y, z] i "If"
prettyPrint' (Num x) i = putStrLn $ concat (replicate i " ")
++ "Num " ++ show x
I am trying to write a show instance to display well formed formula but after miming whole syntax I am still facing the same error as below.
Hugs> :load "C:\\Users\\Devil\\Desktop\\CASESTUDY1.hs"
ERROR file:.\CASESTUDY1.hs:15 - Ambiguous variable occurrence "show"
*** Could refer to: CASESTUDY1.show Hugs.Prelude.show
Below is the content of my .hs file include data type and related show instance .
module CASESTUDY1
where
data Wff = VAR String
| NEG Wff
| AND Wff Wff
| OR Wff Wff
| IMPL Wff Wff
instance Show Wff where
show (VAR x) = x
show (NEG x) = "~" ++ show(x)
show (AND x y) = "(" ++ show(x) ++ "^" ++ show(y) ++ ")"
show (OR x y) = "(" ++ show(x) ++ "v" ++ show(y) ++ ")"
show (IMPL x y) = "(" ++ show(x) ++ "-->" ++ show(y) ++ ")"
In haskell, whitespace is important. You need to indent the show's that belong to your instance of Show.
instance Show Wff where
show (VAR x) = show x
show (NEG x) = "~" ++ show x
show (AND x y) = "(" ++ show x ++ "^" ++ show y ++ ")"
show (OR x y) = "(" ++ show x ++ "v" ++ show y ++ ")"
show (IMPL x y) = "(" ++ show x ++ "-->" ++ show y ++ ")"
Also, you do not need parenthesis to pass the parameters to show. show(x) should be show x.
If you are learning haskell I recommend these exceptional resources:
Learn You a Haskell For Great Good
Real World Haskell
Here is the code:
data Tree t = NilT
| Node t (Tree t) (Tree t)
instance Show (Tree t) where
show NilT = ""
show Node t l r = (show t) ++ ", " ++ (show l) ++ ", " ++ (show r)
how to use "show" in "t show" with the default setting and use "show" with the tree data with the definition given by myself?
In order to use show t, you must add the constraint Show t to your instance definition.
instance Show t => Show (Tree t) where
show NilT = ""
show (Node t l r) = show t ++ ", " ++ show l ++ ", " ++ show r
You were also missing parenthesis around your pattern Node t l r, and I removed the parenthesis around the calls to show, as they were redundant since function application already has the highest precedence.
Just a side note: There is a function Data.List.intersperse for putting a value between list elements.
show (Node t l r) = concat $ intersperse ", " [show t, show l, show r]
Or shorter, as hammar pointed out:
show (Node t l r) = intercalate ", " [show t, show l, show r]
Unfortunately you can't write map show [t, l, r], as the list elements need to have a unique type.
I want to override the default integer constructors in Haskell so they produce strings (mostly for curiosity, but temporarily to make a nice input alternative for LaTeX's \frac{}{} inconvenience).
I wanted to be able to use the language itself, instead of a special parser, but I guess that's probably not going to work out...
module Main where
import Prelude hiding ((+))
newtype A = A Int deriving (Eq, Show, Num)
default (A)
(+) :: A -> (A -> String)
(A a) + (A b) = (show a) ++ " + " ++ (show b)
main2 = 3+4
main :: IO ()
main = putStrLn main2
The problem with the above is that the + function only works for (A, A) instead of (A, String), etc. If one simply leaves out the pattern match "(A a)" and writes "a" instead, then the show() function prepends "A " so "3" becomes "A 3" instead of just "3".
I want to override Show for A, but it seems to be quite a headache...
If you want your own Show instance for A, then just don't derive it and make your own instance:
newtype A = A Int deriving (Eq, Num)
instance Show A where
show (A a) = show a
Then you can write something like:
(+) :: (Show a, Show b) => a -> b -> String
a + b = show a ++ " + " ++ show b
Of course, if you are defining your own + operator like that, then I don't think your problem requires the newtype A declaration:
module Main where
import Prelude hiding ((+))
(+) :: (Show a, Show b) => a -> b -> String
a + b = show a ++ " + " ++ show b
aSum = 3 + 4
main :: IO ()
main = putStrLn aSum
override the default integer constructors in Haskell so they produce strings
So this is done by defining a Num instance for String. Then (+) can be used as String -> String -> String.
A super quick example:
{-# LANGUAGE TypeSynonymInstances #-}
module A where
instance Num String where (+) = (++)
{-
*A> "hello" + "world"
"helloworld"
-}
Write a fromIntegral method to get functions from integer literals to strings (e.g. 1 --> "1").
For a more general, more disciplined approach to lifting lists of Num values to Num, see the Hinze approach to streams as Num, http://hackage.haskell.org/package/hinze-streams
Is this what you are trying to do? Create a numeric type so that you can write expressions in Haskell, and then just print them and have them come out as LaTeX math strings?
module Main where
import Data.Ratio
data LaTeXmath = E Precedence String
deriving (Eq)
data Precedence = Pterm | Pmul | Padd | Pexp
deriving (Show, Eq, Ord, Bounded)
expr :: Precedence -> LaTeXmath -> String
expr p (E q s) | p >= q = s
| otherwise = "\\left(" ++ s ++ "\\right)"
instance Num LaTeXmath where
a + b = E Padd (expr Padd a ++ " + " ++ expr Padd b)
a - b = E Padd (expr Padd a ++ " - " ++ expr Padd b)
a * b = E Pmul (expr Pmul a ++ " " ++ expr Pmul b)
negate a = E Pterm (" -" ++ expr Pterm a)
abs a = E Pterm (" |" ++ expr Pexp a ++ "| ")
signum a = E Pterm (" \\signum (" ++ expr Pexp a ++ ") ")
fromInteger i = E Pterm (show i)
instance Fractional LaTeXmath where
a / b = E Pterm ("\\frac{" ++ expr Pexp a ++ "}{" ++ expr Pexp b ++ "}")
fromRational r = fromInteger num / fromInteger denom
where num = numerator r
denom = denominator r
instance Show LaTeXmath where
show a = "\\[" ++ expr Pexp a ++ "\\]"
sym :: String -> LaTeXmath
sym x = E Pterm x
anExample :: LaTeXmath
anExample = sym "y" / (recip 2 * ( 3 + sym "x" + 2 * sym "y" ) )
main :: IO ()
main = print anExample
This is complicated by the logic required to handle precedence so that parentheses are inserted correctly. The example prints out:
\[\frac{y}{\frac{1}{2} \left(3 + x + 2 y\right)}\]