임의의 수의 인수를 취할 수 있는 함수의 데이터형을 생각하면 모나드가 되었다

11632 단어 Monad하스켈
func1과 func2를 같은 유형으로 만들고 싶습니다.
func1 :: r -> a
func2 :: r -> r -> a

리스트로 인수 건네주면 실행할 수 있으면 좋겠다.
인수가 부족하면 에러로도 할까.
data ManyArgsFunc r a = ????
run :: ManyArgsFunc r a -> [r] -> a

하스켈이라면 재귀
data ManyArgsFunc r a = Pure a | Func (r -> ManyArgsFunc r a)

func1과 func2를 변환할 수 있는지 확인
나중에 실행 함수가 예상대로 될 것인가?
toManyArgsFunc1 :: (r -> a) -> ManyArgsFunc r a
toManyArgsFunc1 func1 = Func $ \r -> Pure (func1 r)

toManyArgsFunc2 :: (r -> r -> a) -> ManyArgsFunc r a
toManyArgsFunc2 func2 = Func $ \r1 -> 
                        Func $ \r2 -> Pure (func2 r1 r2)

-- リストの引数が関数に順番に渡って、Pureまでくれば値を返す。
-- 途中で引数がなくなったらエラー
run :: ManyArgsFunc r a -> [r] -> a
run (Pure a) _ = a
run (Func f) (r:rs) = run (f r) rs

잘 갔다.
여기서 생각했다.
이것, Free 모나드 과 닮았기 때문에 모나드가 되는 것은.
instance Functor (ManyArgsFunc r) where
  fmap f (Pure a) = Pure (f a)
  fmap f (Func g) = Func $ \r -> fmap f (g r)

instance Applicative (ManyArgsFunc r) where
  pure a = Pure a
  (Pure f) <*> x = fmap f x
  (Func g) <*> x = Func $ \r -> (g r) <*> x

instance Monad (ManyArgsFunc r) where
  return a = Pure a
  (Pure a) >>= f = f a
  (Func g) >>= f = Func $ \r -> (g r) >>= f

했어 - 모나드가되었다.

거동으로서는 이런 간지
func1 :: ManyArgsFunc Int String
func1 = Func $ \i -> Func $ \j -> Pure $ show (i + j)

trace :: (Show r , Show a) => ManyArgsFunc r a -> [r] -> String
trace (Pure a) _ = "Pure " ++ show a
trace (Func f) (r:rs) = "Func $ " ++ show r ++ " -> " ++ trace (f r) rs

action :: ManyArgsFunc Int (String,String)
action = do
  a <- func1
  b <- func1
  return (a,b)

>>> run action [1..]
("3","7")

>>> trace action [1..]
Func $ 1 -> Func $ 2 -> Func $ 3 -> Func $ 4 -> Pure ("3","7")

뭔가 도움이 되는 사용법이 생각하면 다시 기사로 합니다.

이미 이와 같은 구조의 모나드 패키지가 있다면 알려주세요.

좋은 웹페이지 즐겨찾기