[英]Creating a fold / catamorphism over ADT with partial monadic functions
我有点不确定,因为我要尝试使用的实际名称是什么,创建折叠或变形效果似乎就是它的名称。
我有以下折叠的数据结构:
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
看来您无法返回这样的部分Monadic函数,但是为什么呢? 我该如何工作呢?
如果要写入某个特定文件,则该文件应该只是write
函数的参数,即write :: FilePath -> Fold IO abc
。 但是据我了解,您想根据实际数据计算文件路径。 在这种情况下,文件路径取决于数据的大小 ,因此这是您需要计算的。 您还需要计算FilePath -> IO ()
类型的延续 FilePath -> IO ()
-您拥有后者,但是缺少前者。
write :: Fold IO () (Int, FilePath -> IO ()) (FilePath -> IO ())
write = (fos, fo, fi) where
fos :: (Int, FilePath -> IO ()) -> (Int, FilePath -> IO ()) -> IO ()
fos (sz1, fo1) (sz2, fo2) = do
let fp = show (sz1 + sz2) ++ ".txt"
sequence_ [fo1 fp, fo2 fp]
fo :: [ FilePath -> IO () ] -> IO (Int, FilePath -> IO ())
fo fis = return (length fis, \fp -> mapM_ ($ fp) fis)
fi :: Int -> IO (FilePath -> IO ())
fi int = return $ \fp -> appendFile fp (show int)
如您所见,原理很简单。 如果您需要一次计算两件事,只需一次计算两件事! 只需添加大小,而将FilePath -> IO ()
类型的函数简单地逐点提升,然后排序即可。
和测试(ghci):
>:! cat 4.txt
cat: 4.txt: No such file or directory
>foldOrders write (Orders [1,2] [3,4])
>:! cat 4.txt
1234>foldOrders write (Orders [1,2] [3,4])
>:! cat 4.txt
12341234>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.