在下面的Haskell代码中,如何更简洁地编写?是否有必要列出所有四个条件,还是可以通过更紧凑的模式进行总结?例如,有没有办法可以利用Haskell已经知道如何添加float和int,而无需手动指定 fromIntegral ?
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)))
答案 0 :(得分: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)