クラスの型変数が特定の他のクラスを派生させる場合にのみ、デフォルトのメソッド実装を定義しようとしています。
を使用して型依存インスタンスを作成しようとしましたが=>
(正しく使用していますか?)、「重複インスタンス宣言エラー」が発生します: ( https://repl.it/@solly_ucko/Distributions )
{-# LANGUAGE FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, InstanceSigs #-}
import Data.Int
import Data.Ratio
import Data.Set
import System.Random
duplicate :: a -> (a, a)
duplicate a = (a, a)
listRange :: Enum a => a -> a -> [a]
listRange a b = [a..b]
class Fractional w => Distribution d v w where
probability :: d v w -> v -> w
probabilityOfRange :: Ord v => d v w -> v -> v -> w
ranges :: (Ord v) => d v w -> Set (v, v)
ranges = (Data.Set.map duplicate) . values
sample :: RandomGen g => d v w -> g -> (v, g)
--sample d g = (scanl1 (+) $ flip Prelude.map $ probability d, g) -- Will need to implement some sort of binary tree, most likely.
sampleIO :: d v w -> IO v
sampleIO = getStdRandom . sample
values :: d v w -> Set v
instance (Ord v, Fractional w) => Distribution d v w where
probability d v = probabilityOfRange d v v
instance Enum v => Distribution d v w where
probabilityOfRange d v1 v2 = sum $ Prelude.map (probability d) [v1..v2]
instance (Enum v, Ord v) => Distribution d v w where
values = fromList . (concatMap $ uncurry listRange) . toList . ranges
次に、実際のインスタンスを追加しようとすると (コンパイラがその時点に到達できるように、以前に作成した「インスタンス」の一部をコメントアウトします)、競合するインスタンスに関するエラーが表示されます。
data Empty v w = Empty
instance Distribution Empty v (Ratio Int8) where
sample _ g = (undefined, g)
sampleIO _ = return undefined
probabilityOfRange _ _ _ = 0
values _ = empty
data Singleton v w = Singleton v
instance Distribution Singleton v Integer where
sample (Singleton v) g = (v, g)
sampleIO (Singleton v) = return v
probabilityOfRange (Singleton v1) v2 v3
| v2 <= v1 && v1 <= v3 = 1
| otherwise = 0
data Uniform v w = Uniform (Set v)
明確にするために、私の目標は for probability
and values
be defined for all Distributions
、および for all for all値を導出するprobabilityOfRange
ように定義することです。また、追加の制約が満たされたときにデフォルトを提供したいと考えています。これがなければ、(他の方法に基づく) 合理的なデフォルトは不可能だからです。Distributions
Ord