是否无法计算Enum类型的maxBound和minBound之间的差异?

Lui*_*las 8 haskell

我是否正确地得出结论,maxBound - minBound在Haskell中无法计算任意EnumBounded类型?或者我错过了一些技巧/黑客?这就是我所拥有的,显然无法运作:

difference :: (Enum a, Bounded a) => Int
difference = fromEnum maxBound - fromEnum minBound
Run Code Online (Sandbox Code Playgroud)

错误:

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
Run Code Online (Sandbox Code Playgroud)

我理解为什么我得到那个错误 - 那里没有类型的实际术语a,所以它无法弄清楚是什么a.问题是,是否有办法解决这个问题.

dav*_*420 12

difference :: (Enum a, Bounded a) => a -> Int
difference x = fromEnum (maxBound `asTypeOf` x) 
             - fromEnum (minBound `asTypeOf` x)
Run Code Online (Sandbox Code Playgroud)

称之为例如difference (undefined :: Char).

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

difference :: (Enum a, Bounded a) => a -> Integer
difference x = toEnum (fromEnum (maxBound `asTypeOf` x)) 
             - toEnum (fromEnum (minBound `asTypeOf` x))
Run Code Online (Sandbox Code Playgroud)


Gab*_*lez 9

使用a 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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

  • 如果要避免扩展,也可以在没有作用域类型变量的情况下完成此操作.`foo :: Bounded a =>代理a - >(a,a); foo _ =(minBound,maxBound); 差值p = let(min,max)= foo p in fromEnum max - fromEnum min` (3认同)
  • 我必须说我喜欢带有幻像类型参数的`Proxy`比使用'undefined`的Dave的答案更好. (2认同)