模式匹配在Haskell再次Num

时间:2016-10-17 11:44:30

标签: haskell

我有一个函数,它接受account并根据它是浮点数,双精度数还是整数执行不同的操作。我发现这样做的唯一方法是使用类型类,但这看起来非常难看。有没有办法匹配任何类型的数字,所以做不同的事情取决于3个Num实例中的哪一个?像

这样的东西
Num

而不是

myFun :: (Num a) => a -> T
myFun n = case n of
  n :: Int -> something for ints
  n :: Float -> something for floats
  n :: Double -> something for doubles

包含class MyClass a where myFun :: (Num a) => a -> T IntFloat的实例?

3 个答案:

答案 0 :(得分:7)

根据我的阅读,这是类型类的教科书应用程序:

module Main where

class Num a => Funnable a where
    myFun :: a -> a

instance Funnable Int where
    myFun = id

instance Funnable Float where
    myFun = (+ 2)

instance Funnable Double where
    myFun = (+ 1)

main :: IO ()
main = do
    print $ myFun (1 :: Int)
    print $ myFun (1 :: Float)
    print $ myFun (1 :: Double)

给出:

$ stack exec example
1
3.0
2.0

如果使用不正确,类型类还会为您提供编译时类型错误。例如,假设我们跳过Double的实例声明:

src/Main.hs:14:13: error:
    • No instance for (Funnable Double) arising from a use of ‘myFun’
    • In the second argument of ‘($)’, namely ‘myFun (1 :: Double)’
      In a stmt of a 'do' block: print $ myFun (1 :: Double)
      In the expression: do { print $ myFun (1 :: Double) }

答案 1 :(得分:6)

你可以建模这样的东西:

data MyNum
    = MDouble Double
    | MInt Int
    | MFloat Float
    deriving (Show,Eq,Ord)

handle :: MyNum -> IO ()
handle (MDouble x) = putStrLn "This is double"
handle (MFloat x) = putStrLn "This is float"
handle (MInt x) = putStrLn "This is int"

事实上,library bson中使用了类似的抽象类型来为Value类型建模。

答案 2 :(得分:3)

另一个,不可否认的是这样做是不错的:

import Data.Typeable

myFunc :: (Typeable a, Num a, Show a) => a -> String
myFunc x 
    | typeOf x == typeOf (0:: Int) = "Its an Int: " ++ show x
    | typeOf x == typeOf (0:: Float) = "Its a Float: " ++ show x
    | typeOf x == typeOf (0:: Double) = "Its a Double: " ++ show x

这个解决方案的弱点是,Num a的实例比上述函数中使用的实例多。因此,在某个时刻,某人会例如致电myFunc 42并感到惊讶,这是一个例外,因为没有案件处理Integer,这也是Num a

相比之下,使用自己的类型类可以缩小可用类型的范围,从而有助于防止异常。

  

*主> myFunc(42 :: Int)
  "它是一个Int:42"
  *主> myFunc(42 :: Float)
  "它的浮动:42.0"
  *主> myFunc(42 :: Double)
  "它是双人:42.0"
  *主> myFunc 42
  " ***异常:Main.hs:(11,1) - (14,66):函数myFunc中的非详尽模式