Van*_*uel 4 io monads haskell pointfree
为什么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"
Run Code Online (Sandbox Code Playgroud)
另外,为什么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
Run Code Online (Sandbox Code Playgroud)
既countInFile1和countInFile3,因为你正在撰写形式的三件事情a -> IO b,你在想所谓Kleisli组成的,在<=<自Control.Monad.尝试
countInFile1 w = putStrLn <=< present w <=< readFile
countInFile3 w = putStrLn <=< return . show . count w <=< readFile
Run Code Online (Sandbox Code Playgroud)
或者你可以countInFile3 w file = ... =<< readFile file像其他地方一样写作.readFile file(带参数)是一个IO String,因此可以通过>>=或传递=<<给任何一个String -> IO b.但这并不像你想要的那样猛烈. readFile只是它本身就是一个FilePath -> IO String所以它可以>=>与任何人String -> IO b一起制作一个FilePath -> IO b等等b -> IO c,在你的情况下以一个结尾FilePath -> IO ()
第二个错误来自ghc尝试读取=<< readFile,为此需要readFilemb为某些monad m,所以它安定下来Monad ((->) FilePath)(这实际上有意义Control.Monad.Instances,但只会延迟得到第一个错误.)
如果你将file参数添加到这些参数,那么,
countInFile1 w file = (putStrLn <=< present w <=< readFile) file
Run Code Online (Sandbox Code Playgroud)
它是可能是因为您解析countInFile2和countInFile0这种方式,而诠释=<<的<=<时候实际上他们是像这样:
countInFile0 w file = putStrLn =<< present w =<< (readFile file)
Run Code Online (Sandbox Code Playgroud)
差异与之间的差异相同
f n = (even . (+1) . (*3)) n
Run Code Online (Sandbox Code Playgroud)
或者等价的
f = even . (+1) . (3*)
Run Code Online (Sandbox Code Playgroud)
而另一方面
f n = even $ (+1) $ 3 * n -- cp. your 0 and 2
Run Code Online (Sandbox Code Playgroud)
如果你n从这里删除双方
f = even $ (+1) $ (3*) -- cp. your 1 and 3
Run Code Online (Sandbox Code Playgroud)
你会得到类似于你所看到的类型错误:
No instance for (Integral (a0 -> a0)) arising from a use of `even'
Run Code Online (Sandbox Code Playgroud)
在您使用的地方,$您需要参数n- 如您使用的位置>>=或=<<您需要参数file.随着.,如<=<,你不知道.