我开始学习Haskell,并找到了这个程序:http://www.haskell.org/haskellwiki/Roll_your_own_IRC_bot/Source。
当我输入它,并使用ghc编译--make 4.hs tutbot时,我收到以下错误:
4.hs:58:10:
Couldn't match expected type `() -> IO b0' with actual type `IO ()'
In the return type of a call of `putStrLn'
Probable cause: `putStrLn' is applied to too many arguments
In the second argument of `bracket', namely `(putStrLn "done.")'
In the expression:
bracket
(printf "Connecting to %s ... " server >> hFlush stdout)
(putStrLn "done.")
a
这是代码:(我已检查嵌入式选项卡并确保所有内容都在同一个组合中):
--
-- Connect to the server and return the initial bot state
--
connect :: IO bot
connect = notify $ do
t <- getClockTime
h <- connectTo server (PortNumber (fromIntegral port))
hSetBuffering h NoBuffering
return (Bot h t)
where
notify a = bracket
(printf "Connecting to %s ... " server >> hFlush stdout)
(putStrLn "done.")
a
-
我看不出问题,似乎没有人遇到过这个问题。
答案 0 :(得分:2)
我认为这是bracket
中的API更改。它的当前类型是
bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
其中第一个动作的结果(“开放”动作)被传递给第二个和第三个动作。这样,打开动作可以返回一个“键”,用于在清理过程中关闭物品。
在此代码段中,a
和(putStrLn "done")
片段都是值,而不是函数。这可能适用于bracket
的旧版本,类型为
bracket :: IO a -> IO b -> IO c -> IO c
此更正可能会修复错误
connect :: IO bot
connect = notify $ \_ -> do
t <- getClockTime
h <- connectTo server (PortNumber (fromIntegral port))
hSetBuffering h NoBuffering
return (Bot h t)
where
notify a = bracket
(printf "Connecting to %s ... " server >> hFlush stdout)
(const $ putStrLn "done.")
a
答案 1 :(得分:1)
问题是bracket
的类型是
IO a -> (a -> IO b) -> (a -> IO c) -> IO c
所以我们用第一个IO a
创建一个资源,附加一个清理,它接受资源a
并在第二部分清理它,然后主块是第三个。
但是putStrLn :: String -> IO ()
所以当应用时它只是IO ()
,而不是() -> IO ()
括号。与a
相同,也不是函数。
这可以通过
轻松解决...
(const $ putStrLn "done")
(const a)
由于我们没有清理任何资源,因此我们忽略了额外的论点。
此外,类型名称始终是capatilized,因此Bot
,而不是bot
答案 2 :(得分:0)
两个小问题。首先,查看bracket
的类型:
bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
第一个参数用于生成资源,第二个用于释放它,第三个用于对其执行有用的操作(可能会抛出异常)。所以第二个和第三个函数接受一个参数,你可以忽略它:
notify a = bracket
(printf "Connecting to %s ... " server >> hFlush stdout)
(\_ -> putStrLn "done.")
(\_ -> a)
其次,您为connect
编写了此类型签名:
connect :: IO bot
bot
这里是一个类型变量;你想要Bot
,一个类型构造函数:
connect :: IO Bot
您的类型签名目前表示connect
会执行一些I / O并返回任何类型的值,它会调用bot
。显然这不可能是真的!