wado

wado

uncurry bimap

bimap であそぶ という記事を書いた。

答えです。

h'' :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)
h'' = uncurry bimap

つまり、こういう感じで書けるってことになりますね。

instance (Applicative m, Monoid w) => Applicative (WriterT w m) where
  (<*>) :: WriterT w m (a -> b) -> WriterT w m a -> WriterT w m b
  mf <*> ma = WriterT $ h <$> runWriterT mf <*> runWriterT ma
    where
      h = uncurry bimap . bimap ($) (<>)

コード

{-# LANGUAGE InstanceSigs #-}
import Data.Bifunctor (bimap, first, second)
import Control.Monad (join)

h0 :: ()
h0 = ()

h1 :: a1 -> b1 -> (a1, b1)
h1 = (,)

h2 :: (a1 -> a2) -> (b1 -> b2) -> (a1, b1) -> (a2, b2)
h2 = bimap

h3 :: (a1 -> a2 -> a3) -> (b1 -> b2 -> b3) -> (a1, b1) -> (a2, b2) -> (a3, b3)
h3 f g = uncurry bimap . bimap f g

newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }

instance Functor m => Functor (WriterT w m) where
  fmap :: (a -> b) -> WriterT w m a -> WriterT w m b
  fmap f = WriterT . fmap (first f) . runWriterT

instance (Applicative m, Monoid w) => Applicative (WriterT w m) where
  pure :: a -> WriterT w m a
  pure = WriterT . pure . second (const mempty) . join (,)

  (<*>) :: WriterT w m (a -> b) -> WriterT w m a -> WriterT w m b
  mf <*> ma = WriterT $ h <$> runWriterT mf <*> runWriterT ma
    where
      -- h (f, w1) (a, w2) = (f a, w1 <> w2)
      h = uncurry bimap . bimap ($) (<>)

h :: (a1 -> a2 -> a3) -> (b1 -> b2 -> b3) -> (a1, b1) -> (a2, b2) -> (a3, b3)
h f g (a1, b1) (a2, b2) = (f a1 a2, g b1 b2)

h' :: (a1 -> a2) -> (b1 -> b2) -> (a1, b1) -> (a2, b2)
h' f g = bimap f g