代码之家  ›  专栏  ›  技术社区  ›  gatoatigrado

如何显示一个新类型的重写?

  •  6
  • gatoatigrado  · 技术社区  · 15 年前

    我想重写haskell中的默认整数构造函数,以便它们生成字符串(主要是出于好奇,但暂时是为了给latex带来的不便提供一个不错的输入替代方案)。

    我想能够使用语言本身,而不是一个特殊的解析器,但我想这可能行不通…

    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”前置,因此“3”将变成“a 3”,而不仅仅是“3”。

    我想取消演出,但似乎很头疼…

    3 回复  |  直到 10 年前
        1
  •  14
  •   MtnViewMark    15 年前

    如果你想要自己的 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
    
        2
  •  7
  •   Don Stewart    15 年前

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

    所以这是通过为字符串定义一个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

        3
  •  5
  •   MtnViewMark    15 年前

    这就是你想做的吗?创建一个数值类型,以便您可以在haskell中编写表达式,然后打印它们并将它们作为乳胶数学字符串输出?

    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)}\]