2009-11-11 4 views
4

В следующем коде Haskell, как это можно записать более лаконично? Нужно ли перечислять все четыре условия, или их можно суммировать с помощью более компактного шаблона? Например, есть ли способ, которым я могу воспользоваться Haskell, уже зная, как добавить float и int, без необходимости вручную указывать fromIntegral?Соответствующие типы данных в 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

Haskell делает не знаю, как добавить Float и Int; он очень специфичен и явно о типах:

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 са С.Б. = SignalFloat (toFloatSig а + toFloatSig б) Если это будет "... (toFloatSig са + toFloatSig С.Б.)"? Благодарю. – Steve

+0

Вы правы, спасибо. – Thomas

+1

Я бы определенно попытался заставить Signal Num работать. –