具有双重和通用编号的操作

时间:2012-04-22 11:09:08

标签: haskell numbers polymorphism double

我想写一个函数,它运行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

我该怎么做才能让它发挥作用?或许我从根本上说错了,不应该这样做?这很奇怪,但我没有在互联网上找到任何关于此的内容。

2 个答案:

答案 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]

另见http://www.haskell.org/haskellwiki/Converting_numbers