8

我是否可以得出结论,maxBound - minBound在 Haskell 中无法计算任意类型EnumBounded类型?还是我错过了一些技巧/黑客?这就是我所拥有的,这显然行不通:

difference :: (Enum a, Bounded a) => Int
difference = fromEnum maxBound - fromEnum minBound

错误:

Foo.hs:37:1:
    Ambiguous constraint `Enum a'
      At least one of the forall'd type variables mentioned by the constraint
      must be reachable from the type after the '=>'
    In the type signature for `difference': difference :: (Enum a, Bounded a) => Int

Foo.hs:37:1:
    Ambiguous constraint `Bounded a'
      At least one of the forall'd type variables mentioned by the constraint
      must be reachable from the type after the '=>'
   In the type signature for `difference': difference :: (Enum a, Bounded a) => Int

我理解为什么会出现该错误- type 中没有实际术语a,因此无法弄清楚是什么a。问题是是否有办法解决这个问题。

4

2 回答 2

12
difference :: (Enum a, Bounded a) => a -> Int
difference x = fromEnum (maxBound `asTypeOf` x) 
             - fromEnum (minBound `asTypeOf` x)

称它为 eg difference (undefined :: Char)

但请注意,对于某些类型(最明显Int的是 ),这会溢出,因此请改用Integer结果:

difference :: (Enum a, Bounded a) => a -> Integer
difference x = toEnum (fromEnum (maxBound `asTypeOf` x)) 
             - toEnum (fromEnum (minBound `asTypeOf` x))
于 2012-11-05T21:44:43.357 回答
9

使用 aProxy指定您想要的类型,并使用ScopedTypeVariables该类型将该类型纳入函数定义的范围。

{-# LANGUAGE ScopedTypeVariables #-}

data Proxy a = Proxy

difference :: forall a . (Enum a, Bounded a) => Proxy a -> Int
difference Proxy = fromEnum (maxBound :: a) - fromEnum (minBound :: a)

>>> difference (Proxy :: Proxy Bool)
1

编辑:使用丹尼尔的建议:

data Proxy a = Proxy

difference :: (Enum a, Bounded a) => Proxy a -> Int
difference p = fromEnum (max' p) - fromEnum (min' p) where
    max' :: (Bounded a) => Proxy a -> a
    max' Proxy = maxBound
    min' :: (Bounded a) => Proxy a -> a
    min' Proxy = minBound
于 2012-11-05T21:26:12.897 回答