gpt4 book ai didi

haskell - 无意义编程时 readFile 和 IO monad 之间没有合作

转载 作者:行者123 更新时间:2023-12-02 02:52:01 26 4
gpt4 key购买 nike

为什么 countInFile1 & countInFile3 有编译器错误,而 countInFile0 & countInFile2 没有。这四个都是一样的。

count :: String -> String -> Int
count w = length . filter (==w) . words

present :: String -> String -> IO String
present w = return . show . count w

-- VALID: pointed readFile, regular present
countInFile0 :: String -> FilePath -> IO ()
countInFile0 w f = putStrLn =<< present w =<< readFile f

-- INVALID: pointless readFile, regular present
countInFile1 :: String -> FilePath -> IO ()
countInFile1 w = putStrLn =<< present w =<< readFile

-- VALID: pointed readFile, inline present
countInFile2 :: String -> FilePath -> IO ()
countInFile2 w f = putStrLn =<< (return . show . count w) =<< readFile f

-- INVALID: pointless readFile, inline present
countInFile3 :: String -> FilePath -> IO ()
countInFile3 w = putStrLn =<< (return . show . count w) =<< readFile

main = do
countInFile0 "bulldogs" "bulldogs.txt"
countInFile1 "bulldogs" "bulldogs.txt"
countInFile2 "bulldogs" "bulldogs.txt"
countInFile3 "bulldogs" "bulldogs.txt"

还有为什么 countInFile3 有这个额外的错误,而 countInFile1 没有:
example_one.hs:21:27:
No instance for (Monad ((->) FilePath))
arising from a use of `=<<'
Possible fix:
add an instance declaration for (Monad ((->) FilePath))
In the expression:
putStrLn =<< (return . show . count w) =<< readFile
In an equation for `countInFile3':
countInFile3 w
= putStrLn =<< (return . show . count w) =<< readFile

最佳答案

与两者 countInFile1countInFile3 ,因为您正在编写形式为 a -> IO b 的三件事,你在想所谓的 Kleisli 作文,<=<来自 Control.Monad .尝试

 countInFile1 w = putStrLn <=< present w <=< readFile
countInFile3 w = putStrLn <=< return . show . count w <=< readFile

或者你可以写 countInFile3 w file = ... =<< readFile file ,就像您在其他地方所做的那样。 readFile file (带参数)是一个 IO String ,所以它可以通过 >>= 传递或 =<<给任何 String -> IO b .但这并不像你想要的那么时髦。 readFile本身就是一个 FilePath -> IO String所以它可以是 >=> 'd 与任何 String -> IO b制作 FilePath -> IO b以此类推 b -> IO c等,在您的情况下以 FilePath -> IO () 结尾

第二个错误来自 ghc 试图读取 =<< readFile , 为此需要 readFile对于某些 monad m 来说是 m b,所以它决定于 Monad ((->) FilePath) (这实际上对 Control.Monad.Instances 有意义,但只会延迟获得第一个错误。)

如果添加 file这些参数是这样的,
 countInFile1 w file = (putStrLn <=< present w <=< readFile) file 

并且您可能正在解析 countInFile2countInFile0这样,同时解释 =<<<=<实际上他们是这样的:
 countInFile0 w file = putStrLn =<< present w =<< (readFile file)

区别是相同的
 f n = (even . (+1) . (*3)) n

或等效地
 f   = even . (+1) . (3*)

另一方面
 f n = even $ (+1) $ 3 * n  -- cp. your 0 and 2

如果删除 n从这里两边
 f   = even $ (+1) $ (3*)  -- cp. your 1 and 3

你会得到一个类似于你看到的类型错误:
 No instance for (Integral (a0 -> a0)) arising from a use of `even'

您在哪里使用 $您需要参数 n -- 就像你使用的地方 >>==<<您需要参数 file .与 . ,与 <=< 一样,你没有。

关于haskell - 无意义编程时 readFile 和 IO monad 之间没有合作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12470078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com