
Suppose I have one piece of code like this:
class Result r e | r -> e where failure :: e -> r a success :: a -> r a
at :: Result r String => [a] -> Int -> r a at xs i = if i >= 0 && i < length xs then success (xs !! i) else failure "Wrong index"
Either instance of Result is quite straightforward:
instance Result (Either e) e where failure e = Left e success x = Right x
Maybe instance is discarding failure information:
instance Result Maybe e where failure _ = Nothing success x = Just x
Some tests it in ghci: ghci> let xs = [0,1,2] ghci> at xs 2 :: Either String Integer Right 2 ghci> at xs 3 :: Either String Integer Left "Wrong index" ghci> at xs 2 :: Maybe Integer Just 2 ghci> at xs 3 :: Maybe Integer Nothing I'd like to replace functional dependencies with type families (associated types in my case):
class Result r where type Failure failure :: Failure r -> r a success :: a -> r a
Either instance is ok:
instance Result (Either e) where type Failure (Either e) = e failure e = Left e success x = Right x
But what to do with Maybe?
instance Result Maybe where type Failure Maybe = forall e. e -- can't do this failure _ = Nothing success x = Just x