비맵으로 놀아요.

17291 단어 Haskelltech
transformers 포장WriterT의 정의를 고려한다.
newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }

Functor 인스턴스


Functor의 인스턴스는 적분 없이 간단하게 작성할 수 있습니다.
import Data.Bifunctor (first)

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

Applicative Functor 인스턴스


그런 다음 Applicative Functor의 인스턴스를 작성합니다.
instance (Applicative m, Monoid w) => Applicative (WriterT w m) where
  pure :: a -> WriterT w m a
  pure a = WriterT $ pure (a, mempty)
이 정의를 면적분으로 설정하는 것은 아까보다 더 어려운 것 같지만 간단하다.
import Data.Bifunctor (second)
import Control.Monad (join)

instance (Applicative m, Monoid w) => Applicative (WriterT w m) where
  pure :: a -> WriterT w m a
  pure = WriterT . pure . second (const mempty) . join (,)
<*>도 정의해 보세요.
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 (f, w1) (a, w2) = (f a, w1 <> w2)
대충 이런 느낌이에요.여기서 국부 정의h의 무적분을 어떻게 씁니까?
이를 위해서는 일반화h부터 고려해야 한다.

bimap

h 일반화하면 아래가 이렇게 되겠죠.
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)
원조의 각 요소에 서로 다른 함수를 응용했기 때문에bimap 사용할 수 있을 것 같다.
h' :: (a1 -> a2) -> (b1 -> b2) -> (a1, b1) -> (a2, b2)
h' f g = bimap f g
하지만 이것은 예상대로 활동할 수 없다.(a2->a3, b2->b3)처럼 결과 유형의 원조 내부에 함수가 있기 때문이다.
-- a2 = a2 -> a3, b2 = b2 -> b3 として型を変形
h' :: (a1 -> a2 -> a3) -> (b1 -> b2 -> b3) -> (a1, b1) -> (a2 -> a3, b2 -> b3)
h' f g = bimap f g
(a2 -> a3, b2 -> b3) -> (a2, b2) -> (a3, b3)의 함수를 찾으면 함수h는 점 없이 쓸 수 있다는 것이다.
h'' :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)
h'' = undefined
대답은 스스로 생각해 보세요 (1시간 정도 걸렸어요)

좋은 웹페이지 즐겨찾기