我是USB驱动程序和Haskell的新手。我正在尝试使用System.USB连接到Tomu(适合USB端口的ARM微控制器)。我尝试了以下示例:https : //github.com/basvandijk/usb-example/blob/master/example.hs,但是已经过时了几年。我正在尝试在USB上打个招呼,但出现类型错误。
以下代码有效:
module Lib where
import System.USB
import System.USB.IO
import Data.Vector
import Data.Maybe
getOneDesc :: Int -> IO (VendorId, ProductId)
getOneDesc n = do
usbConn <- newCtx
devList <- getDevices usbConn
f <- getDeviceDesc $ devList ! n
let f0 = deviceVendorId f
let f1 = deviceProductId f
return (f0, f1)
Run Code Online (Sandbox Code Playgroud)
在repl处,我可以键入getOneDesc 0,然后得到如下所示的内容:
(300, 42)
Run Code Online (Sandbox Code Playgroud)
我认为我应该能够做这样的事情:
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> Bool
isThisDeviceTheOneIWant n a b = do
(x, y) <- getOneDesc n
return (x == a) && (y == b)
Run Code Online (Sandbox Code Playgroud)
但是我遇到类型错误。
有人可以看到这是怎么回事吗?
您getOneDesc是一个IO (VendorId, ProductId),因此表示您的结果类型为return (x == a) && (y == b)类型IO Bool。因此,您应该更改函数的类型。您还必须在要传递的参数周围加上括号return(因为在Haskell中,return它不是关键字,而只是一个普通函数)。
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> IO Bool
isThisDeviceTheOneIWant n a b = do
(x, y) <- getOneDesc n
return ((x == a) && (y == b))Run Code Online (Sandbox Code Playgroud)
您不能使isThisDeviceTheOneIWantreturn为a Bool,因为return为getOneDesc an IO (VendorId, ProductId),并且您也不aIO a能使an 退出。
就像@DanielWagner所说的,我们可以使用fmap :: Functor f => (a -> b) -> f a -> f b来处理的结果getOneDesc n,例如:
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> IO Bool
isThisDeviceTheOneIWant n a b = fmap ((a, b) ==) (getOneDesc n)Run Code Online (Sandbox Code Playgroud)
或使用(<$>) :: Functor f => (a -> b) -> f a -> f b与fmap:
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> IO Bool
isThisDeviceTheOneIWant n a b = ((a, b) ==) <$> getOneDesc nRun Code Online (Sandbox Code Playgroud)