How does one override show for a newtype?
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)}\]
精彩评论