0

私がしようとしているものの実際の名前が何であるかは少しわかりません。折り畳みまたはカタモルフィズムを作成することがその名前のようです。

折り畳みのある次のデータ構造があります。

type Order = [Int]
data Orders = Orders FilePath Order Order

type FoldOrders m o os = FilePath -> o -> o -> m os
type FoldOrder m o i = [i] -> m o
type FoldInt m i = Int -> m i

type Fold m os o i = (FoldOrders m o os, FoldOrder m o i, FoldInt m i)

foldOrders :: (Monad m) => Fold m os o i -> Orders -> m os
foldOrders (fos, fo, fi) (Orders orders1 orders2) = do o1 <- foldOrder orders1
                                                       o2 <- foldOrder orders2
                                                       fos o1 o2
    where foldOrder order = do o <- mapM foldInt order
                               fo o
          foldInt int     = fi int

この折り畳みは、たとえば次の「実装」でうまく機能します。

simpleWrite :: Fold IO () () ()
simpleWrite = (fos, fo, fi)
where fos _ _ = return ()
      fo  _   = return ()
      fi  i   = putStrLn $ show i

このコマンドの使用

foldOrders simpleWrite (Orders [1,2] [3,4])

1 2 3 4期待どおりに印刷されます。

ここまではいいんだけど..

次のようにデータ構造を歩いているときに、いくつかの情報 (この場合はファイルパス) を「プッシュ」したい場合:

write :: Fold IO a b c
write = (fos, fo, fi)
     where fos path fo1 fo2 = do _ <- fo1 path
                                 _ <- fo2 path
                                 return ()
           fo fis path = do ios <- mapM (\x -> x path) fis
                            return ()           
           fi int path = appendFile path $ show int

私はそれをコンパイルすることができません。次のエラーが返されます。

Couldn't match type `FilePath -> IO ()' with `IO c'
Expected type: FoldInt IO c
  Actual type: Int -> FilePath -> IO ()
In the expression: fi

このように部分モナド関数を返すことはできないようですが、なぜですか? どうすればこれを機能させることができますか?

4

1 に答える 1