为什么countInFile1& countInFile3& countInFile3有编译错误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
答案 0 :(得分:9)
同时使用countInFile1
和countInFile3
,因为您正在撰写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
>=>
所以String -> IO b
可以FilePath -> IO b
与任何b -> IO c
建立FilePath -> IO ()
,依此类推=<< readFile
在您的情况下以readFile
第二个错误来自ghc尝试阅读Monad ((->) FilePath)
,为此需要Control.Monad.Instances
为某些monad m为mb,因此它会在file
上结算(这实际上会使感知 countInFile1 w file = (putStrLn <=< present w <=< readFile) file
,但只是延迟得到第一个错误。)
如果您将countInFile2
参数添加到这些参数,那么
countInFile0
并且您可能正在以这种方式解析=<<
和<=<
,同时将 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
或.
一样,您需要参数<=<
。对于{{1}},与{{1}}一样,您没有。{/ p>
答案 1 :(得分:8)
函数应用程序的优先级高于infix =<<
运算符。
所以f =<< g a
相当于f =<< (g a)
而不是(f =<< g) a
。