[Haskell-beginners] System.USB.writeInterrupt -- confused by error message from type system

emacstheviking objitsu at gmail.com
Wed Feb 27 22:06:30 CET 2013


HURRAH! I have finally got it to compile...

I manually deleted the broken packages (I play too much anyway so a tidy up
was in order) and it still failed with:

[1 of 1] Compiling Main             ( usb1.hs, usb1.o )

usb1.hs:64:28:
    Couldn't match expected type
`bytestring-0.9.2.1:Data.ByteString.Internal.ByteString'
                with actual type `ByteString'
    In the first argument of `action', namely `payload'
    In a stmt of a 'do' block: (size, status) <- action payload 1000
    In the expression:
      do { putStrLn $ "Inspecting device: \"" ++ (show dev) ++ "\"";
           let payload = BS.replicate 64 '\NUL';
           let endPoint = EndpointAddress 0 Out;
           let action = writeInterrupt handle endPoint;
           .... }
And I suddenly remembered that despite the clean up I still had two
bytestring packages:

sean at sean-Dimension-4700 ~/Documents/haskell/usb $ ghc-pkg list bytestring
/var/lib/ghc/package.conf.d
   bytestring-0.9.2.1
/home/sean/.ghc/i386-linux-7.4.2/package.conf.d
   bytestring-0.10.0.2

So, on the basis that the system is always right and I am always wrong I
removed the local one in my home folder:

sean at sean-Dimension-4700 ~/Documents/haskell/usb $ ghc-pkg unregister
bytestring-0.10.0.2

and then tried again:

sean at sean-Dimension-4700 ~/Documents/haskell/usb $ ghc --make usb1.hs
Linking usb1 ...

sean at sean-Dimension-4700 ~/Documents/haskell/usb $ sudo ./usb1
Inspecting device: "Bus 005 Device 002"
libusbx: error [submit_bulk_transfer] submiturb failed error -1 errno=2
usb1: IOException ""
*
*
For me that *is* *success*, it fails because since I wrote it I read the
USB docs again and I have to "claim" the device before I can talk to the
endpoint but at least I am now focused on my goal of USB interaction with
the Hexwax chip again.

A big thanks to everybody, this list is once again proving to be awesome,
another happy user walks away :)

Thanks everybody, especially Karol, Alexander and David.

Sean Charles.

*PS: Yes, I am using a a Dell from 2004 because as much as I'd love to but
a shiny new iMac I cant bring myself to part with my trusty friend. Hell, I
even wrote my own computer language system with it and it's "good enough".
Shameless plug (http://feltweb.info, site written in FELT!)  Still
under-way, doing "Java" with it of late, not finished yet because USB and
hardware is more fun right now!
*





On 27 February 2013 19:21, David McBride <toad3k at gmail.com> wrote:

> You have this line in your code, but that doesn't correlate to the imports
> you listed.
>
> BS.replicate 64 '\0'
>
>     import qualified Data.ByteString          as B  ( ByteString,
> packCStringLen, drop, length )
>     import qualified Data.ByteString.Internal as BI ( createAndTrim,
> createAndTrim' )
>     import qualified Data.ByteString.Unsafe   as BU (
> unsafeUseAsCStringLen )
>
> So you must have imported Data.ByteString.Lazy as BS somewhere.  Change
> that to B.replicate and it will probably work.
>
>
> On Wed, Feb 27, 2013 at 11:41 AM, emacstheviking <objitsu at gmail.com>wrote:
>
>> Karol, Alexander,
>>
>> Thanks for your feedback... I am still a little confused as I shall
>> explain... first of all let's look at the prototype for 'writeInterrupt',
>>
>>
>>     writeInterrupt :: DeviceHandle -> EndpointAddress -> WriteAction
>>
>> To me, that reads a "takes a device handle and an endpoint address and
>> returns a WriteAction", and to quote the WriteAction help text verbatim so
>> there is no confusion:
>>
>>     type WriteAction = ByteString -> Timeout -> IO (Size, Status)Source
>>
>>     Handy type synonym for write transfers.
>>
>>         "A WriteAction is a function which takes a ByteString to write
>> and a Timeout.
>>          The function returns an IO action which, when exectued(sic),
>> returns the number
>>          of bytes that were actually written paired with a Status flag
>> which indicates whether
>>          the transfer Completed or TimedOut."
>>
>>
>> Now let's move to my original code and the 'right' code...
>>
>>     action <- writeInterrupt handle endPoint
>>     let action = writeInterrupt handle endPoint
>>
>>
>> If I understand things correctly up to this point, my mistake was being
>> too eager in using "<-", my mind at that point was obviously confusing the
>> return value from WriteAction with the return type of writeInterrupt and I
>> can see now that what I should have done was use "let" which captures the
>> WriteAction that is returned which can be executed with the payload and the
>> timeout on the next line:
>>
>>     (size, status) <- action payload 1000
>>
>> On this line, the use of "<-" is what is required in order to cause the
>> promised IO action to  perform its duties and return me the tuple of data
>> sent and status returned from the USB inner workings.
>>
>> However, we now come to the new type checker error, and this one has me
>> floored right now. Time and time again I find myself beating my head
>> against a wall and tearing my hair out trying to understand the
>> thousand-and-one variations on strings in Haskell! I even tried the
>> "string-conversions" (convertString) package but decided to battle it out
>> instead...
>>
>> First the new code as edited in response to Karol:
>>
>>
>>     testBoard :: Device -> DeviceHandle -> IO ()
>>     testBoard dev handle = do
>>
>>       putStrLn $ "Inspecting device: \"" ++ (show dev) ++ "\""
>>        -- write 0x00 0x00 0x00 0x00, get back same...we need to pad
>> the
>>       -- packet out to 64 bytes for a full-speed device... should
>> probably
>>       -- get this (64) from the device configuration / description
>> record
>>       -- for maximum
>> portability!
>>
>>       let payload  = BS.replicate 64 '\0'
>>
>>       let endPoint = EndpointAddress 0 Out
>>       let action   = writeInterrupt handle endPoint
>>       (size, status) <- action payload 1000
>>       return ()
>>
>> And the new error:
>>
>> usb1.hs:64:28:
>>     Couldn't match expected type
>> `bytestring-0.9.2.1:Data.ByteString.Internal.ByteString'
>>                 with actual type `ByteString'
>>     In the first argument of `action', namely `payload'
>>     In a stmt of a 'do' block: (size, status) <- action payload 1000
>>
>>     In the expression:
>>       do { putStrLn $ "Inspecting device: \"" ++ (show dev) ++ "\"";
>>            let payload = BS.replicate 64 '\NUL';
>>            let endPoint = EndpointAddress 0 Out;
>>            let action = writeInterrupt handle endPoint;
>>            .... }
>>
>>
>> Where and why does it think that "Data.ByteString.Internal.ByteString" is
>> the type of the first parameter to "action" which is quite clearly stated
>> as being "ByteString" ???
>> I know that "String", the native type is 4-bytes and that ByteString
>> (Strict) and ByteString (Lazy) are both 8-bit, which is great, and I
>> understand that the strict version (at least to me) feels like the
>> rightmatch to be using for data buffers for a USB transfer but why oh why
>> oh why can't I understand why the type checker picked up "internal"
>> somewhere along the way?
>>
>> In the source code for WriteAction we have this:
>>
>>     type WriteAction = B.ByteString → Timeout → IO (Size, Status)
>>
>> and at the top of the that source file:
>>
>>     -- from bytestring:
>>     import qualified Data.ByteString          as B  ( ByteString,
>> packCStringLen, drop, length )
>>     import qualified Data.ByteString.Internal as BI ( createAndTrim,
>> createAndTrim' )
>>     import qualified Data.ByteString.Unsafe   as BU (
>> unsafeUseAsCStringLen )
>>
>>
>> So why is it trying to be "internal"! I have tried not to be lazy, I have
>> read everything and looked everywhere before posting again. If it had said:
>>
>>     type WriteAction = BI.ByteString → Timeout → IO (Size, Status)
>>
>> I would have understood but it doesn't does it ?!
>> Can somebody explain for me so I can just get on and write my killer USB
>> application please! LOL
>>
>> :)
>> Thanks,
>> Sean.
>>
>>
>>
>>
>>
>> On 27 February 2013 12:07, Karol Samborski <edv.karol at gmail.com> wrote:
>>
>>> Hi Sean,
>>>
>>> I think that your function for testing board should look like this:
>>>
>>> testBoard :: Device -> DeviceHandle -> IO ()
>>> testBoard dev handle = do
>>>   putStrLn $ "Inspecting device: \"" ++ (show dev) ++ "\"\n"
>>>   -- write 0x00 0x00 0x00 0x00, get back same...
>>>   let payload  = pack "\x00\x00\x00\x00"
>>>   let endPoint = EndpointAddress 0 Out
>>>   let action = writeInterrupt handle endPoint
>>>   (size, status) <- action payload 1000
>>>   return ()
>>>
>>> You need to use let because writeInterrupt returns (Timeout ->
>>> ByteString -> IO (Size, Bool)) instead of IO (Timeout -> ByteString ->
>>> IO (Size, Bool))
>>>
>>> Karol
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> Beginners at haskell.org
>>> http://www.haskell.org/mailman/listinfo/beginners
>>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20130227/49b7942f/attachment.htm>


More information about the Beginners mailing list