Help us understand the problem. What is going on with this article?

任意の数の引数を取れる関数のデータ型を考えてたらモナドになった

More than 1 year has passed since last update.

func1とfunc2を同じ型にしたい。

func1 :: r -> a
func2 :: r -> r -> a

リストで引数渡したら実行できるといいな。
引数が足りなかったらエラーにでもしようかな。

data ManyArgsFunc r a = ????
run :: ManyArgsFunc r a -> [r] -> a

Haskellといえば再帰

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

うまくいった。:relaxed:
ここで思った。
これ、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")

なにか役に立つ使い方が思いつけばまた記事にします。

もし、すでにこれと同じ構造のモナドのパッケージがあれば教えてください

sgmryk
普段はPHP使いです。 最近はHaskellがマイブーム。モナモナ。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away