8

maxBound - minBoundHaskell で任意Enumの型を計算する方法はないと結論付けるのは正しいBoundedでしょうか? または、いくつかのトリック/ハックがありませんか? これは私が持っているものであり、明らかに機能しません:

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)

たとえば のように呼び出し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

を使用し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
于 2012-11-05T21:26:12.897 に答える