Właśnie próbowałem owijać moją głowę wokół wolnych monad; jako pomoc w nauce, udało mi się napisać instancji Show
na następny Free
typu:Czy mogę wyeliminować użycie UndecidableInstances w tej instancji Show dla darmowej monady?
{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}
-- Free monad datatype
data Free f a = Return a | Roll (f (Free f a))
instance Functor f => Monad (Free f) where
return = Return
Return a >>= f = f a
Roll ffa >>= f = Roll $ fmap (>>= f) ffa
-- Show instance for Free; requires FlexibleContexts and
-- UndecidableInstances
instance (Show (f (Free f a)), Show a) => Show (Free f a) where
show (Return x) = "Return (" ++ show x ++ ")"
show (Roll ffx) = "Roll (" ++ show ffx ++ ")"
-- Identity functor with Show instance
newtype Identity a = Id a deriving (Eq, Ord)
instance Show a => Show (Identity a) where
show (Id x) = "Id (" ++ show x ++ ")"
instance Functor (Identity) where
fmap f (Id x)= Id (f x)
-- Example computation in the Free monad
example1 :: Free Identity String
example1 = do x <- return "Hello"
y <- return "World"
return (x ++ " " ++ y)
Zastosowanie UndecidableInstances
denerwuje mnie nieco; czy istnieje sposób, aby obejść się bez niego? Wszystko, co Google zyskuje, to this blog post by Edward Kmett, co pocieszająco ma w zasadzie taką samą definicję klasy jak ja.
"UndecidableInstances" nie jest tak naprawdę niepokojąca. Zasadniczo wystarczy, że kompilator "zaufa mi, instancja goni się zakończy". Jeśli zrobisz to źle, stos kontekstowy nadal będzie zatrzymywał kompilator od utknięcia w nieskończonej pętli. –