2010-04-18 28 views
6

Tôi muốn ghi đè lên các hàm tạo số nguyên mặc định trong Haskell để chúng tạo ra các chuỗi (hầu hết là tò mò, nhưng tạm thời để tạo một thay thế đầu vào tốt cho sự bất tiện của LaTeX \) {}.Làm cách nào để ghi đè hiển thị cho một loại mới?

tôi muốn để có thể sử dụng ngôn ngữ riêng của mình, thay vì một cú pháp đặc biệt, nhưng tôi đoán đó là có lẽ sẽ không làm việc ra ...

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 

Vấn đề với bên trên là + chức năng chỉ hoạt động cho (A, A) thay vì (A, String), v.v. Nếu đơn giản chỉ bỏ qua mẫu phù hợp "(A a)" và viết "a" thay vào đó, hàm show() sẽ thêm "A" vì vậy "3" trở thành "A 3" thay vì chỉ "3".

Tôi muốn ghi đè Show khác cho việc A, nhưng nó có vẻ là khá đau đầu ...

Trả lời

14

Nếu bạn muốn riêng Show dụ bạn cho A, sau đó chỉ cần không lấy được nó và làm cho dụ của riêng bạn:

newtype A = A Int deriving (Eq, Num) 

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

Sau đó, bạn có thể viết một cái gì đó như:

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

Tất nhiên, nếu bạn đang định + điều hành riêng của mình như vậy, sau đó tôi không nghĩ vấn đề của bạn đòi hỏi sự newtype A khai:

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

Cảm ơn, nhưng nó không phải là rất compositional: 3 + 4 + 2 sản lượng '"3 + 4" + 2'. Xin lỗi vì đã là một newbie ... nếu bạn biết cách để giải quyết vấn đề này, tôi sẽ đánh giá cao điều đó! Cảm ơn bạn đã chỉ ra vấn đề chính - xuất hiện Hiển thị. – gatoatigrado

+0

Ok - bây giờ tôi nghĩ rằng tôi hiểu những gì bạn đang cố gắng làm. Xem câu trả lời thứ hai của tôi. Nó sẽ xử lý 3 + 4 + 2 một cách chính xác. – MtnViewMark

+0

Bạn có thể sử dụng kiểu chữ Monoid cho chức năng "+" đó. –

7

ghi đè các nhà thầu nguyên mặc định trong Haskell để họ tạo ra chuỗi

Vì vậy, đây được thực hiện bằng cách xác định một thể hiện Num cho String. Sau đó, (+) có thể được sử dụng như String -> String -> String.

Một ví dụ siêu nhanh:

{-# LANGUAGE TypeSynonymInstances #-} 

module A where 

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

{- 

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

-} 

Viết một phương pháp fromIntegral để có được chức năng từ literals số nguyên thành các chuỗi (ví dụ 1 -> "1").

Đối với một cách tiếp cận tổng quát hơn, kỷ luật hơn để nâng danh sách các giá trị num để Num, xem cách tiếp cận Hinze với suối như Num, http://hackage.haskell.org/package/hinze-streams

+0

Điều này trông giống như một giải pháp tốt đẹp, nhưng nó làm cho ghci nhổ ra rất nhiều cảnh báo ... và chức năng này trông như thế nào? Cảm ơn rất nhiều! – gatoatigrado

5

Đây có phải là những gì bạn đang cố gắng để làm gì? Tạo một kiểu số để bạn có thể viết các biểu thức trong Haskell, và sau đó chỉ cần in chúng và đặt chúng thành các chuỗi toán 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 

Điều này phức tạp do logic cần thiết để xử lý mức ưu tiên sao cho dấu ngoặc đơn được chèn chính xác. Ví dụ in ra:

\[\frac{y}{\frac{1}{2} \left(3 + x + 2 y\right)}\] 
Các vấn đề liên quan