2010-04-18 6 views
6

Voglio sovrascrivere i costruttori di numeri interi predefiniti in Haskell in modo da produrre stringhe (principalmente per curiosità, ma temporaneamente per fare una bella alternativa di input per l'inconveniente di \ frac {} {} di LaTeX.Come viene mostrato un override per un newtype?

volevo essere in grado di usare la lingua in sé, invece di un parser speciale, ma credo che probabilmente non è andare a lavorare fuori ...

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 

Il problema con quanto sopra è che il + la funzione funziona solo per (A, A) anziché (A, String), ecc. Se si lascia semplicemente la corrispondenza del modello "(A a)" e si scrive "a", la funzione show() antepone "A" quindi "3" diventa "A 3" anziché solo "3".

voglio ignorare Show per A, ma sembra essere un bel mal di testa ...

risposta

14

Se si desidera che il proprio Show istanza per A, allora semplicemente non fare derivarlo e rendere il vostro propria istanza:

newtype A = A Int deriving (Eq, Num) 

instance Show A where 
    show (A a) = show a 

Quindi è possibile scrivere qualcosa di simile:

(+) :: (Show a, Show b) => a -> b -> String 
a + b = show a ++ " + " ++ show b 

Naturalmente, se si sta definendo il proprio operatore di + così, allora non credo che il problema richiede la dichiarazione newtype A:

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 
+0

Grazie, ma non è molto compositivo: 3 + 4 + 2 produce "" 3 + 4 "+ 2". Scusa per essere un principiante ... se conosci un modo per aggirare questo, lo apprezzerei molto! Grazie per aver evidenziato il problema principale - derivando Show. – gatoatigrado

+0

Okay - ora penso di capire cosa stai cercando di fare. Vedi la mia seconda risposta. Gestirà correttamente 3 + 4 + 2. – MtnViewMark

+0

È possibile utilizzare la classe di tipi Monoid per tale funzionalità "+". –

7

esclusione dei costruttori di default interi a Haskell in modo da produrre corde

Quindi questo è fatto definendo un'istanza Num per String. Quindi (+) può essere usato come String -> String -> String.

Un esempio di super veloce:

{-# LANGUAGE TypeSynonymInstances #-} 

module A where 

instance Num String where (+) = (++) 

{- 

*A> "hello" + "world" 
"helloworld" 

-} 

Scrivi un metodo fromIntegral per ottenere funzioni dal letterali interi in stringhe (ad esempio 1 -> "1").

Per un più generale approccio, più disciplinato di sollevamento elenchi di valori Num per Num, vedere l'approccio Hinze ai flussi come Num, http://hackage.haskell.org/package/hinze-streams

+0

Questo appare come una bella soluzione, ma rende ghci sputare fuori un sacco di avvertimenti ... e in che modo questa funzione fromIntegral guardare? Grazie mille! – gatoatigrado

5

E 'questo ciò che si sta cercando di fare? Creare un tipo numerico in modo da poter scrivere espressioni in Haskell, quindi stamparle e farle apparire come stringhe matematiche LaTeX?

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 

Questo è complicata dalla logica necessaria per gestire la precedenza cosicché parentesi sono inserite correttamente. L'esempio viene stampato:

\[\frac{y}{\frac{1}{2} \left(3 + x + 2 y\right)}\] 
Problemi correlati