繁体   English   中英

如何在 Haskell 中重构这些 IO 操作?

[英]How can I refactor these IO operations in Haskell?

我刚刚制作了一个脚本,它从 TSV 文件中获取一些值并以不同的方式格式化它们。 脚本如下所示:

{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}

import qualified Data.Text as T
import qualified Data.Text.IO as TIO

tsvToPat tsv = T.unlines $ map (makePat . (T.replace "-" " ") . head . (T.splitOn "\t")) (T.lines tsv)

main :: IO ()
main = do
  pantone <- TIO.readFile "../data/maps/pantone/pantone.tsv"
  xkcd <- TIO.readFile "../data/maps/xkcd/rgb.txt"
  jaffer <- TIO.readFile "../data/maps/jaffer/master.tsv"
  TIO.putStr $ tsvToPat pantone
  TIO.putStr $ tsvToPat xkcd
  TIO.putStr $ tsvToPat jaffer


makePat :: T.Text -> T.Text
makePat pat = T.concat [ "{\"label\":\"COLOR\",\"pattern\":[{\"lower\":\""
                       , pat
                       , "\"}]}"
                       ]

但我正在努力思考如何重构主要 function 中的所有内容。 我想做的是:

maps :: [FilePath]
maps = [ "../data/maps/pantone/pantone.tsv"
       , "../data/maps/xkcd/rgb.txt"
       , "../data/maps/jaffer/master.tsv"
       ]

main = map (TIO.putStr . tsvToPat . TIO.readFile) maps

这是行不通的,因为我猜它是将 IO 操作与纯函数混合在一起。 我应该在这里使用一些神奇的单子绑定运算符吗?

您正在寻找的一元绑定运算符是<=<来自Control.Monad 它的作用类似于 monad 运算符的 function 组合。 您还需要将map升级到一元映射 function mapM_ 例如,忽略tsvToPat位,您可以编写:

main = mapM_ (TIO.putStr <=< TIO.readFile) maps

弄清楚如何将纯 function 像tsvToPat挤进去可能有点棘手。 一种方法是通过编写return. tsvToPat return. tsvToPat ,所以你得到:

main' :: IO ()
main' = mapM_ (TIO.putStr <=< return . tsvToPat <=< TIO.readFile) maps

注意 的优先级. 这里高于<=<

尽管该版本使一切都非常清楚,但实际上可以简化为:

main :: IO ()
main = mapM_ (TIO.putStr . tsvToPat <=< TIO.readFile) maps

do中的操作阻止对>>=的调用进行脱糖,并且有一个名为=<<的翻转版本。 要运行 IO 操作列表,请使用mapM_ 把这些概念放在一起,你会得到:

main = mapM_ (\x -> TIO.putStr . tsvToPat =<< TIO.readFile x) maps

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM