haskell - 与 Haskell 交互使用串行端口

标签 haskell serial-port nxt

我正在尝试使用 Haskell 的交互模式通过串行端口向 Lego NXT 发送消息,但我不知道如何使用 serialport功能正常。

我有一条消息应该在 NXT 上播放 ByteString 类型的提示音

> let message = pack ([6, 0 ,0, 3, 224, 1, 208, 7]::[Word8])

我可以使用openSerial打开串行端口。

openSerial :: FilePath -> SerialPortSettings -> IO SerialPort
> let mybrick = openSerial "/dev/tty.NXT-DevB" defaultSerialSettings

但后来我陷入困境。我应该如何使用send功能?

send :: SerialPort -> B.ByteString -> IO Int
> send mybrick message

这给了我以下错误消息。

<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

最佳答案

您需要对您的 Monad 计算进行排序。我会根据您的情况写得笼统、简单。

<小时/>

你遇到的问题是你有一个函数 f::A -> IO B 和另一个函数 g::B -> IO C 感觉它们应该可以组合,但不完全是——第二个函数需要一个plain B,而不是第一个函数返回的IO B .

这正是 Monad 的力量发挥作用的地方。知道 IO 是一个 monad,我们可以使用像 (>=>)::Monad m => (a -> m b) -> (b -> m c) -> 这样的函数a -> m c 组合这些 Monad 函数。事实上,f >=> g::A -> IO C 已经像我们所要求的那样了。

我们还可以使用 do 表示法,这需要我们“绑定(bind)”f 的返回类型,然后将其应用于 g获取输出。

\a -> do b <- f a
         g b

这又给了我们一个A -> IO C类型的函数。事实上,这个do表示法基本上就是(>=>)的定义。

<小时/>

那么这如何适用于您的特定情况呢?嗯,

let mybrick = openSerial "/dev/tty.NXT-DevB" defaultSerialSettings

为您提供一个mybrick::IO SerialPort值。为了使用 send::SerialPort -> ByteString -> IO Int,我们需要从 IO Monad 中“解开”mybrick 。所以我们可以使用 do 表示法

do sp <- mybrick
   send sp message

或者,为了让一切变得更简洁,我们可以使用 do 表示法运行整个计算

do mybrick <- openSerial "/dev/tty.NXT-DevB" defaultSerialSettings
   send mybrick message

关于haskell - 与 Haskell 交互使用串行端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16246277/

相关文章:

python - 如何设计和实现编程语言?

结合陀螺仪和加速度计数据

python - 显式设置方法的文档字符串

c++ - 在Windows中通过串口写入二进制数据

C# 如何在 C# 中刷新串口

haskell - 主要功能错误

mongodb - 从 Haskell MongoDB 驱动程序中检索错误状态

haskell - do block 中的返回类型

haskell - 如何反序列化 JSON,其中相应的 Haskell 类型在运行时可作为值使用?

c - 将 rs232 编程为 lcd (Linux)