I am trying to define default method implementations, but only if the class's type variables derive certain other classes.
I have tried creating type-dependent instances using =>
(am I even using it correctly?), but I get a "duplicate instance declaration error": (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
When I then try to add real instances (and comment out some of the "instances" I created earlier so that the compiler can reach that point), it gives me an error about conflicting instances.
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)
To clarify, my goal is for probability
and values
to be defined for all Distributions
, and for probabilityOfRange
to be defined for all Distributions
with values deriving Ord
. I also wish to provide defaults when additional constraints are met, because without them, a reasonable default (based on other methods) is impossible.