为什么我不能在这里放一个打印函数语句?
Why can't I put a print function statement here?
我正在尝试使用 try-catch 块执行以下代码:
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 语句,错误就会消失,程序运行良好。
为什么我不能在这个函数中放入打印语句?
您可能会对在 toTry
中工作的相同打印行感到困惑,但在 isBinary
中却不会。差异源于声明:
isBinary :: String -> Bool
这意味着 isBinary
是一个纯函数(即没有副作用),接受一个字符串并返回一个布尔值。事实上,您可以将其简化为
isBinary ss = any (\c -> ord c > 127) ss
甚至使用 point-free 样式
isBinary = any (\c -> ord c > 127)
然而,toTry
是
toTry :: String -> IO ()
即它需要一个字符串和 returns 不纯的 IO
monad(可能有副作用,例如将文本打印到控制台)。
Haskell 是一种鼓励使用纯函数的语言,并通过强制程序员显式标记不纯代码来强制使用类型系统。
延伸阅读:
What does "pure" mean in "pure functional language"?
答案是,"because types"。具体来说:
isBinary :: String -> Bool
isBinary ss = do
....
因为它是一个 do
块,所以 isBinary
的 return 类型必须 匹配一些单子类型 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
块属于 IO
monad,因为 print
;其次,由于整个函数的 return 类型。
改为使用
return ans
现在它可以工作了,因为 return
将一个值注入到 monadic 上下文中,并且作为最后一个 do
块值,它成为 do
块产生的值整体(如果 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
在左边。
有关 do
表示法的一般说明,请参阅 。
查看您的代码,您在 isBinary
中对 print
的使用似乎不是您希望函数执行的操作的组成部分,而只是将被删除的调试打印语句稍后的。在这种情况下,您不想将 isBinary
的类型更改为 String -> IO Bool
(有关更多信息,请参阅 ), as you don't actually need IO
except for debugging. Rather, the core libraries offer the Debug.Trace
module,它迎合了这种情况。有了它,我们可以像这样添加调试打印语句:
isBinary :: String -> Bool
isBinary ss = trace "In isBinary fn" $ any (\c -> ord c > 127) ss
然后,完成调试后,您可以删除 trace
的使用——值得重复,您确实应该稍后再这样做。引用 Debug.Trace
文档:
Functions for tracing and monitoring execution.
These can be useful for investigating bugs or performance problems. They should not be used in production code.
我正在尝试使用 try-catch 块执行以下代码:
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 语句,错误就会消失,程序运行良好。
为什么我不能在这个函数中放入打印语句?
您可能会对在 toTry
中工作的相同打印行感到困惑,但在 isBinary
中却不会。差异源于声明:
isBinary :: String -> Bool
这意味着 isBinary
是一个纯函数(即没有副作用),接受一个字符串并返回一个布尔值。事实上,您可以将其简化为
isBinary ss = any (\c -> ord c > 127) ss
甚至使用 point-free 样式
isBinary = any (\c -> ord c > 127)
然而,toTry
是
toTry :: String -> IO ()
即它需要一个字符串和 returns 不纯的 IO
monad(可能有副作用,例如将文本打印到控制台)。
Haskell 是一种鼓励使用纯函数的语言,并通过强制程序员显式标记不纯代码来强制使用类型系统。
延伸阅读: What does "pure" mean in "pure functional language"?
答案是,"because types"。具体来说:
isBinary :: String -> Bool
isBinary ss = do
....
因为它是一个 do
块,所以 isBinary
的 return 类型必须 匹配一些单子类型 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
块属于 IO
monad,因为 print
;其次,由于整个函数的 return 类型。
改为使用
return ans
现在它可以工作了,因为 return
将一个值注入到 monadic 上下文中,并且作为最后一个 do
块值,它成为 do
块产生的值整体(如果 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
在左边。
有关 do
表示法的一般说明,请参阅
查看您的代码,您在 isBinary
中对 print
的使用似乎不是您希望函数执行的操作的组成部分,而只是将被删除的调试打印语句稍后的。在这种情况下,您不想将 isBinary
的类型更改为 String -> IO Bool
(有关更多信息,请参阅 IO
except for debugging. Rather, the core libraries offer the Debug.Trace
module,它迎合了这种情况。有了它,我们可以像这样添加调试打印语句:
isBinary :: String -> Bool
isBinary ss = trace "In isBinary fn" $ any (\c -> ord c > 127) ss
然后,完成调试后,您可以删除 trace
的使用——值得重复,您确实应该稍后再这样做。引用 Debug.Trace
文档:
Functions for tracing and monitoring execution.
These can be useful for investigating bugs or performance problems. They should not be used in production code.