{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Nes.APU.State.Filter.Class (Filter (..)) where

import Nes.APU.State.Filter.Constants

class Filter m a where
    consume :: Sample -> a -> m a
    output :: a -> m Sample

instance (Monad m, Filter m a, Filter m b) => Filter m (Either a b) where
    consume :: Sample -> Either a b -> m (Either a b)
consume Sample
sample = (a -> m (Either a b))
-> (b -> m (Either a b)) -> Either a b -> m (Either a b)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((a -> Either a b) -> m a -> m (Either a b)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Either a b
forall a b. a -> Either a b
Left (m a -> m (Either a b)) -> (a -> m a) -> a -> m (Either a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sample -> a -> m a
forall (m :: * -> *) a. Filter m a => Sample -> a -> m a
consume Sample
sample) ((b -> Either a b) -> m b -> m (Either a b)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> Either a b
forall a b. b -> Either a b
Right (m b -> m (Either a b)) -> (b -> m b) -> b -> m (Either a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sample -> b -> m b
forall (m :: * -> *) a. Filter m a => Sample -> a -> m a
consume Sample
sample)
    output :: Either a b -> m Sample
output = (a -> m Sample) -> (b -> m Sample) -> Either a b -> m Sample
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (m :: * -> *) a. Filter m a => a -> m Sample
output @m) (forall (m :: * -> *) a. Filter m a => a -> m Sample
output @m)