2009-11-11 64 views
4

在下面的Haskell代碼中,這怎麼寫得更簡潔?是否有必要列出所有四個條件,或者可以通過更緊湊的模式來總結這些條件?例如,有沒有辦法我可以利用Haskell已經知道如何添加一個float和一個int,而不必手動指定從Haskell中的模式匹配數據類型。捷徑?

data Signal = SignalInt Int | SignalFloat Float | Empty deriving (Show) 

sigAdd :: Signal -> Signal -> Signal 
sigAdd (SignalInt a) (SignalInt b) = SignalInt (a + b) 
sigAdd (SignalInt a) (SignalFloat b) = SignalFloat ((fromIntegral a) + b) 
sigAdd (SignalFloat a) (SignalInt b) = SignalFloat (a + (fromIntegral b)) 
sigAdd (SignalFloat a) (SignalFloat b) = SignalFloat (a + b) 

main :: IO() 
main = do 
    putStrLn (show (sigAdd (SignalFloat 2) (SignalInt 5))) 

回答

7

哈斯克爾不知道如何添加一個FloatInt;它是非常具體和明確的關於類型:

Prelude> (5 :: Int) + 3.5 

<interactive>:1:13: 
    No instance for (Fractional Int) 
     arising from the literal `3.5' at <interactive>:1:13-15 
    Possible fix: add an instance declaration for (Fractional Int) 
    In the second argument of `(+)', namely `3.5' 
    In the expression: (5 :: Int) + 3.5 
    In the definition of `it': it = (5 :: Int) + 3.5 

定義一個函數toFloatSig

toFloatSig (SignalInt a) = fromIntegral a 
toFloatSig (SignalFloat a) = a 

然後,你可以寫:

sigAdd (SignalInt a) (SignalInt b) = SignalInt (a + b) 
sigAdd sa sb = SignalFloat (toFloatSig sa + toFloatSig sb) 

它也可能是適當的做Signal實例的Num class,以便您可以直接使用+運算符添加它們。此外,您還可以使類型更通用:

data (Num a) => Signal a = Signal a | Empty deriving (Show) 
+0

> sigAdd SA SB = SignalFloat(toFloatSig A + toFloatSig B) 如果這是 「...(toFloatSig SA + SB toFloatSig)」?謝謝。 – Steve 2009-11-11 18:46:31

+0

你說得對,謝謝。 – Thomas 2009-11-11 18:53:57

+1

我一定會讓Signal Num工作。 – 2009-11-11 21:17:23