Haskell 一个覆盖如何显示一个新类型?

Haskell 一个覆盖如何显示一个新类型?,haskell,show,typeclass,Haskell,Show,Typeclass,我想覆盖Haskell中的默认整数构造函数,以便它们生成字符串(主要是出于好奇,但暂时是为了更好地替代LaTeX的\frac{}{}不便) 我希望能够使用语言本身,而不是一个特殊的解析器,但我想这可能不会奏效 module Main where import Prelude hiding ((+)) newtype A = A Int deriving (Eq, Show, Num) default (A) (+) :: A -> (A -> String) (A a) + (

我想覆盖Haskell中的默认整数构造函数,以便它们生成字符串(主要是出于好奇,但暂时是为了更好地替代LaTeX的\frac{}{}不便)

我希望能够使用语言本身,而不是一个特殊的解析器,但我想这可能不会奏效

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
上面提到的问题是,+函数只适用于(A,A)而不是(A,String)等。如果省略模式匹配“(A)”而改为写入“A”,那么show()函数会在“A”之前加上“A”,因此“3”将变成“a3”,而不仅仅是“3”

我想在一段时间内取代这个节目,但这似乎是一个相当头痛的问题

重写Haskell中的默认整数构造函数,以便它们生成字符串

这是通过为String定义一个Num实例来实现的。然后(+)可以用作字符串->字符串->字符串

一个超级快速的例子:

{-# LANGUAGE TypeSynonymInstances #-}

module A where

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

{-

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

-}
编写一个fromIntegral方法,将函数从整数文本转换为字符串(例如,1-->“1”)


有关将Num值列表提升到Num的更一般、更严格的方法,请参阅将streams作为Num的Hinze方法,

如果您希望自己的
a
显示
实例,则只需不派生它并创建自己的实例:

newtype A = A Int deriving (Eq, Num)

instance Show A where
  show (A a) = show a
然后你可以写一些类似的东西:

(+) :: (Show a, Show b) => a -> b -> String
a + b = show a ++ " + " ++ show b
当然,如果您是这样定义自己的
+
运算符,那么我认为您的问题不需要
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

这就是你想做的吗?创建一个数值类型,这样您就可以在Haskell中编写表达式,然后只需打印它们并将它们作为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
处理优先级所需的逻辑使这一点变得复杂,以便正确插入括号。该示例打印出:

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

谢谢,但它不是很复杂:3+4+2产生“3+4+2”。很抱歉我是个新手。。。如果你能想出一个办法,我将不胜感激!谢谢你指出了主要的问题——衍生秀。好吧,现在我想我明白你想做什么了。见我的第二个答案。它将正确处理3+4+2。您可以使用MonoidTypeClass实现“+”功能。这看起来是一个不错的解决方案,但它会让ghci发出很多警告。。。这个积分函数看起来怎么样?非常感谢!