8

我想覆盖 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)”并改为写“a”,那么show() 函数在“A”前面加上“3”,而不仅仅是“3”。

我想覆盖A的Show,但这似乎很头疼......

4

3 回答 3

16

如果你想要你自己的Show实例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
于 2010-04-18T02:34:17.863 回答
7

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

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

一个超级快速的例子:

{-# LANGUAGE TypeSynonymInstances #-}

module A where

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

{-

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

-}

编写一个 fromIntegral 方法来获取从整数文字到字符串的函数(例如 1 --> "1")。

有关将 Num 值列表提升到 Num 的更通用、更规范的方法,请参阅 Hinze 将流作为 Num 的方法,http://hackage.haskell.org/package/hinze-streams

于 2010-04-18T01:58:10.037 回答
5

这是你想要做的吗?创建一个数字类型,以便您可以在 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)}\]
于 2010-04-18T06:05:55.643 回答