Ответ таков: «потому что печатает ».В частности:
isBinary :: String -> Bool
isBinary ss = do
....
Поскольку это блок do
, тип возвращаемого значения isBinary
должен соответствовать монадическому типу 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
из-за print
;и во-вторых, из-за типа возврата функции в целом.
Вместо этого используйте
return ans
, и теперь это будет работать, потому что return
вводит значение в монадический контекст и, будучи последним значением 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
слева.
См. this для общегоописание do
обозначения.