Monday 15 February 2010

How to write an expression over a data type and print it out in haskell? -



How to write an expression over a data type and print it out in haskell? -

i having write look build poly representation of polynomial x^3 + x + 1.

my algebraic info type poly, wrote is:

data poly = lit integer | var | add together poly poly | mul poly poly

the look can think of this, how can able print out result using print()?:

expr::poly->poly expr = add together (lit 1) $ add together (var) $ mul (var) $ mul var var

also, i'd write function this:

showpoly::poly->string showpoly (lit x) = show x showpoly (var) = "x" showpoly (add x y) = (show x) ++ " + " ++ (show y) showpoly (mul x y) = (show x) ++ "*" ++ (show y)

to enable passing of poly look , converting string. however, above work tells me have no instance (show poly), not sure mean.

first of all, expr has wrong type. expr :: poly correct. inquire ghci type:

> :t add together (lit 1) $ add together (var) $ mul (var) $ mul var var add together (lit 1) $ add together (var) $ mul (var) $ mul var var :: poly

in order utilize print or similar function, type needs instance of show, since

print :: show => -> io ()

one way accomplish derive show instance automatically:

data poly = .... deriving (show)

however, won't lead desired result "x^3 + x + 1". need write show instance yourself, example:

instance show poly show (add x y) = "(" ++ show x ++ ") * (" ++ show y ++ ") show (mul x y) = "(" ++ show x ++ ") * (" ++ show y ++ ") show (lit x) = show x show (var) = "x"

note still isn't you're looking for:

> show expr "(1) + ((x) + ((x) * ((x) * (x))))"

however, info should enable create own instance.

another way solve problem implement showsprec method of show typeclass. function threads through precedence can take when apply parentheses, allowing print out look looks more 1 + x + x * x * x instead of simple illustration using show above. type of showsprec little wonky, though, looks like

showsprec :: show => int -> -> shows

where

type shows = string -> string

the shows type encoding diff list, allows more efficient construction of strings through function composition rather simple concatenation. poly type, want implement this:

instance show poly showsprec d poly = case poly of lit -> shows var -> showstring "x" add together l r -> showparen (d > add_prec) $ showsprec add_prec l . showstring " + " . showsprec add_prec r mul l r -> showparen (d > mul_prec) $ showsprec mul_prec l . showstring " * " . showsprec mul_prec r -- infixl 6 + add_prec = 6 -- infixl 7 * mul_prec = 7

the d parameter represents precedence. each phone call check if precedence greater of each operator, , if adds parentheses around look (showparen conditionally puts parentheses around shows), , builds left , right trees of look right precedence. precedences of 6 , 7 come asking ghci :i (+) , :i (*), show fixity (precedence) of each operator respectively.

with instance can utilize write readable instances well:

instance num poly (+) = add together (*) = mul negate = mul (lit (-1)) frominteger = lit abs = undefined signum = undefined

keep in mind isn't exclusively behaved due undefineds, allows write code like

x :: poly x = var expr1 :: poly expr1 = 1 + x + x * x * x expr2 :: poly expr2 = 2 * (x + 3 * x) expr3 :: poly expr3 = (4 + x) * (4 * (x + 2) * x + x * (x + x + 4))

and test:

> :l poly.hs > expr1 1 + x + x * x * x > expr2 2 * (x + 3 * x) > expr3 (4 * x) * (4 * (x + 2) * x + x * (x + x + 4))

which identical how defined in source code.

haskell

No comments:

Post a Comment