我想写一个函数,它运行double和任何其他类型的数字,支持乘法和加法,结果产生double。 当然,下面的代码不能编译,因为(*)的类型是t - > t - > t,所以不允许混合使用不同的类型:
f :: (Num a) => Double -> a -> a -> Double
f x a b = a*x + b
我想要的是能够写出这样的东西:
f :: ...
f x a b = ... -- equivalent to a*x + b
f 1.0 (2 :: Int) (3 :: Int) -- returns 5.0
f 1.0 (2 :: Word32) (3 :: Word32) -- returns 5.0
f 1.0 (2 :: Float) (3 :: Float) -- returns 5.0
我该怎么做才能让它发挥作用?或许我从根本上说错了,不应该这样做?这很奇怪,但我没有在互联网上找到任何关于此的内容。
答案 0 :(得分:3)
在RWH.chapter6中有一个关于在某些数字类型(表6.4)之间转换数字的好段落。
f :: (Real a) => Double -> a -> a -> Double
f x a b = x * (cast a) + (cast b)
where cast = fromRational . toRational
似乎可行。
> f 1.0 (2 :: Int) (3 :: Int)
5.0
it :: Double
> f 1.0 (2 :: Word32) (3 :: Word32)
5.0
it :: Double
> f 1.0 (2 :: Float) (3 :: Float)
5.0
it :: Double
答案 1 :(得分:1)
使用类型类的机制进行“重载”:
import Data.Word
import GHC.Float
class F a where f :: Double -> a -> a -> Double
instance F Int where f x a b = fromIntegral a * x + fromIntegral b
instance F Word32 where f x a b = fromIntegral a * x + fromIntegral b
instance F Float where f x a b = float2Double a * x + float2Double b
tests =
[ f 1.0 (2 :: Int) (3 :: Int)
, f 1.0 (2 :: Word32) (3 :: Word32)
, f 1.0 (2 :: Float) (3 :: Float)
]
-- > tests
-- [5.0,5.0,5.0]
-- > :t it
-- it :: [Double]