模式匹配在Haskell再次Num

shm*_*111 4 haskell

我有一个函数,Num取决于它是浮点数,双精度还是整数取一个并做不同的事情.我发现这样做的唯一方法是使用类型类,但这看起来非常难看.有没有办法匹配任何类型的数字,所以做不同的事情取决于3个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
Run Code Online (Sandbox Code Playgroud)

而不是

class MyClass a where
  myFun :: (Num a) => a -> T
Run Code Online (Sandbox Code Playgroud)

与实例Int,Float,Double

Mic*_*kis 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)
Run Code Online (Sandbox Code Playgroud)

得到:

$ stack exec example
1
3.0
2.0
Run Code Online (Sandbox Code Playgroud)

如果使用不正确,类型类也会为您提供编译时类型错误.例如,假设我们跳过了实例声明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) }
Run Code Online (Sandbox Code Playgroud)


Sib*_*ibi 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"
Run Code Online (Sandbox Code Playgroud)

实际上,在库bson中使用了类似的抽象类型来建模它的Value类型.