我正在尝试使用 try-catch block 跟踪代码:
import System.Environment
import System.IO
import System.IO.Error
import Control.Exception
isBinary :: String -> Bool
isBinary ss = do
print "In isBinary fn" -- works if this line is removed.
let ans = any (\c -> ord c > 127) ss
ans
toTry :: String -> IO ()
toTry firline = do
print "In toTry fn."
let answer = isBinary firline
if not answer then do
print "Sent line not binary: "
else
print "Sent line binary"
handler :: IOError -> IO ()
handler e = putStrLn "Whoops, had some trouble!"
ss = "this is a test"
main = do
toTry ss `catch` handler
但是,我收到以下错误:
$ runghc trycatch3.hs
trycatch3.hs:9:9: error:
• Couldn't match expected type ‘Bool’ with actual type ‘IO Bool’
• In a stmt of a 'do' block: print "in isBinary fn"
In the expression:
do { print "in isBinary fn";
let ans = any (\ c -> ...) ss;
return ans }
In an equation for ‘isBinary’:
isBinary ss
= do { print "in isBinary fn";
let ans = ...;
return ans }
trycatch3.hs:10:30: error:
• Variable not in scope: ord :: Char -> Integer
• Perhaps you meant one of these:
‘or’ (imported from Prelude), ‘odd’ (imported from Prelude)
如果从 isBinary 函数中删除 print 语句,错误就会消失,程序运行良好。
为什么我不能在这个函数中放入打印语句?
最佳答案
答案是,“因为类型”。具体来说:
isBinary :: String -> Bool
isBinary ss = do
....
因为它是 do
block ,isBinary
的返回类型必须 匹配单子(monad)类型 Monad m => m t
对于一些 m
还有一些t
.在这里,因为 print "" :: IO ()
, m
是IO
, 所以应该是
isBinary :: String -> IO Bool
isBinary ss = do
现在
print "In isBinary fn" -- works
let ans = any (\c -> ord c > 127) ss -- also works
ans -- doesn't work
ans
再次因为类型而不起作用。它的类型是 Bool
, 但它必须是 IO Bool
-- 首先,因为这个 do
block 属于 IO
monad,由于 print
;其次,因为整个函数的返回类型。
相反,使用
return ans
现在它可以工作了,因为return
向 monadic 上下文中注入(inject)一个值,并且是最后一个 do
block 值,它成为 do
产生的值整体 block (如果 return val
出现在中间,它只是将 val
传递到组合计算的下一步)。
函数toTry
必须扩充才能使用新定义:
toTry :: String -> IO ()
toTry firline = do
print "In toTry fn."
-- let answer = isBinary firline -- incorrect, now!
answer <- isBinary firline -- isBinary ... :: IO Bool
if not answer then do -- answer :: Bool
print "Sent line not binary: "
else
print "Sent line binary"
m a
在 <-
的右侧, a
在左边。
参见 this有关 do
的一般说明符号。
关于haskell - 为什么我不能在这里放一个打印函数语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56220932/