Estou tentando implementar algo genérico semelhante a um anel e aplicá-lo a uma estrutura de dados de música descrita por Paul Hudak no livro The Haskell School of Music. Naturalmente, há muitas travessuras de Semigrupo/Monóide que são omitidas, mas tenho o seguinte código relevante:
newtype Duo a b = Duo {duo1 :: a} -- A ring-like structure
data Song a =
Primitive a
| Song a :+: Song a -- Composing Music Sequentially
| Song a :=: Song a deriving Eq -- Composing Music Concurrently (in parallel)
instance Functor Song where
fmap f (x :+: y) = fmap f x :+: fmap f y
fmap f (x :=: y) = fmap f x :=: fmap f y
fmap f (Primitive x) = Primitive $ f x
newtype Concurrent a = Concurrent {fromConcurrent :: Song a} deriving (Show)
newtype Sequential a = Sequential {fromSequential :: Song a} deriving (Show)
type Music a = Duo (Maybe (Concurrent a)) (Maybe (Sequential a))
Estou tentando escrever uma instância do Functor for Music, como o Duo não tem um Functor, pensei que isso não seria um problema.
Escrevi a seguinte implementação:
instance Functor Music where
fmap :: (a -> b) -> Music a -> Music b
fmap f = Duo . fmap (fmap f . fromConcurrent) . duo1
Mas recebo o seguinte erro:
• The type synonym ‘Music’ should have 1 argument, but has been given none • In the instance declaration for ‘Functor Music’ | 167 | instance Functor Music where | ^^^^^^^^^^^^^
Talvez o problema seja apenas que estou essencialmente escrevendo um Functor apenas para um subconjunto de Duo, talvez isso só funcione se eu fizer da música um novo tipo em vez de apenas um sinônimo de tipo. Eu realmente espero evitar isso devido ao número já flagrante de wrappers acontecendo neste código, eu realmente odiaria adicionar outro. Talvez todos vocês possam pensar em uma maneira de implementar um functor para o Duo que faça sentido e faça tudo funcionar?
Uma coisa que eu realmente não entendo é por que vamos fazer uma instância para mostrar:
instance (Show a) => Show (Music a) where
show (Duo Nothing) = "Silence"
show (Duo (Just (Concurrent x))) = show x