首页 > 解决方案 > Haskell - 如何泛化 Float 和 Double

问题描述

我有一个简单的类型类,用于表示连续概率分布,有一个实例。我想尽可能通用地编写类型类和公式,例如,我可以根据需要在 Float 或 Double 之间进行选择。

这不会编译:

class ContinuousDistribution d where
    ppf :: Floating a => d -> a -> a

data Uniform = Uniform
     { lowerBound :: Float
     , upperBound :: Float
     } deriving (Show)

instance ContinuousDistribution Uniform where
    ppf d q = (1.0 - q) * lowerBound d + q * upperBound d

生产

stats.hs:10:27: error:
    • Couldn't match expected type ‘a’ with actual type ‘Float’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          ppf :: forall a. Floating a => Uniform -> a -> a
        at stats.hs:10:5
    • In the second argument of ‘(*)’, namely ‘lowerBound d’
      In the first argument of ‘(+)’, namely ‘(1.0 - q) * lowerBound d’
      In the expression: (1.0 - q) * lowerBound d + q * upperBound d
    • Relevant bindings include
        q :: a (bound at stats.hs:10:11)
        ppf :: Uniform -> a -> a (bound at stats.hs:10:5)
Failed, modules loaded: none.

在类型类声明中指定类型可以编译,但将我限制为 Float。

class ContinuousDistribution d where
    ppf :: d -> Float -> Float

data Uniform = Uniform
     { lowerBound :: Float
     , upperBound :: Float
     } deriving (Show)

instance ContinuousDistribution Uniform where
    ppf d q = (1.0 - q) * lowerBound d + q * upperBound d

修改类型类以便我可以根据需要使用 Float 或 Double 的规范方法是什么?

标签: haskell

解决方案


让您的分布参数数据结构由Floating实例参数化:

data Uniform a = Uniform
     { lowerBound :: a
     , upperBound :: a
     } deriving (Show)

class ContinuousDistribution d where
    ppf :: Floating a => d a -> a -> a

instance ContinuousDistribution Uniform where
    ppf d q = (1.0 - q) * lowerBound d + q * upperBound d

推荐阅读