首页 文章

Haskell中的模式匹配数据类型 . 捷径?

提问于
浏览
4

在下面的Haskell代码中,如何更简洁地编写它?是否有必要列出所有四个条件,还是可以通过更紧凑的模式进行总结?例如,有没有一种方法可以利用Haskell已经知道如何添加一个浮点数和一个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)))

1 回答

  • 7

    Haskell不知道如何添加 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)
    

相关问题