我有权得出结论认为,在Haskell中无法使用任意Enum
和Bounded
类型计算maxBound - minBound
?还是我错过了一些技巧/骇客?这就是我所拥有的,显然无法正常工作:
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
我理解为什么要遇到这个错误 - 使用a
类型的实际术语没有实际术语,因此它无法弄清楚a
是什么。问题是是否有办法解决这个问题。
difference :: (Enum a, Bounded a) => a -> Int
difference x = fromEnum (maxBound `asTypeOf` x)
- fromEnum (minBound `asTypeOf` x)
称其为例如difference (undefined :: Char)
。
但请注意,这将溢出某些类型(最著名的是Int
),因此请使用Integer
结果:
difference :: (Enum a, Bounded a) => a -> Integer
difference x = toEnum (fromEnum (maxBound `asTypeOf` x))
- toEnum (fromEnum (minBound `asTypeOf` x))
使用Proxy
指定您想要的类型,并使用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