iha*_*ter 2 haskell serial-port nxt
我想通过串口使用Haskell的交互模式乐高NXT发送消息,但我无法弄清楚如何使用的SerialPort正常功能.
我有一条消息,应该在类型的NXT上播放音调 ByteString
> let message = pack ([6, 0 ,0, 3, 224, 1, 208, 7]::[Word8])
Run Code Online (Sandbox Code Playgroud)
我可以使用打开串口openSerial.
openSerial :: FilePath -> SerialPortSettings -> IO SerialPort
> let mybrick = openSerial "/dev/tty.NXT-DevB" defaultSerialSettings
Run Code Online (Sandbox Code Playgroud)
但后来我卡住了.我该如何使用该send功能?
send :: SerialPort -> B.ByteString -> IO Int
> send mybrick message
Run Code Online (Sandbox Code Playgroud)
这给我以下错误信息.
<interactive>:31:6:
Couldn't match expected type `SerialPort'
with actual type `IO SerialPort'
In the first argument of `send', namely `mybrick'
In the expression: send mybrick message
In an equation for `it': it = send mybrick message
Run Code Online (Sandbox Code Playgroud)
你需要排序的Monad计算.我会写一般的,然后专门针对你的情况.
你遇到的问题是你有一个功能f :: A -> IO B和另一个功能g :: B -> IO C,他们觉得它们应该是可以组合的,但并不完全---第二个功能需要一个简单的 B,而不是IO B第一个返回的功能.
这正是Monads 的力量发挥作用的地方.知道这IO是一个monad,我们可以使用类似于(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c组合这些Monadic函数的函数.事实上,已经f >=> g :: A -> IO C像我们要求的那样.
我们还可以使用do表示法,它要求我们"绑定"返回类型,f然后应用它g来获取输出.
\a -> do b <- f a
g b
Run Code Online (Sandbox Code Playgroud)
这给了我们一个类型的功能A -> IO C.实际上,这种do符号基本上是定义的(>=>).
那么这在您的特定情况下如何适用?好,
let mybrick = openSerial "/dev/tty.NXT-DevB" defaultSerialSettings
Run Code Online (Sandbox Code Playgroud)
给你一个mybrick :: IO SerialPort价值.为了使用send :: SerialPort -> ByteString -> IO Int,我们需要"解开" mybrick从IO Monad.所以我们可以使用do符号
do sp <- mybrick
send sp message
Run Code Online (Sandbox Code Playgroud)
或者,为了使一切更整洁,我们可以使用do符号运行整个计算
do mybrick <- openSerial "/dev/tty.NXT-DevB" defaultSerialSettings
send mybrick message
Run Code Online (Sandbox Code Playgroud)