?

Log in

No account? Create an account
ru_declarative [entries|archive|friends|userinfo]
ru_declarative

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Типы данных для бинарного протокола [Jul. 21st, 2009|12:59 pm]
ru_declarative
ru_declarative
[braintrace]
[Tags|]
[Current Location |Russian Federation, Санкт-Петербург]

Решил написать на Haskell encoder/decoder для некоего бинарного протокола. И почти сразу же появились вопросы.
  1. Как кодировать данные? Сначала на ум пришло использовать классы типов:
    
    import qualified Data.ByteString.Char8 as B
    
    class Encodable a where
        encode :: a -> B.ByteString
    
    -- Int, Integer кодируется одинаково, я добился этого функцией со следующей сигнатурой
    encodeIntegral :: (Bits a, Integral a, Num a) => a -> B.ByteString
    
    -- И делаем Int, Integer экземплярами Encodable
    instance Encodable Int where
        encode = encodeIntegral
    instance Encodable Integer where
        encode = encodeIntegral
    
    Тогда вопрос — почему в Real World Haskell для решения аналогичной проблемы при работе с JSON определяется тип данных JValue? Какие в этом преимущества? Почему нельзя было и там обойтись классом типов?

  2. Как поступить с обратным преобразованием? Можно определить функцию:
    
    decode :: (Encodable a) => B.ByteString -> a
    
    Но если мы дадим вот такую реализацию для decode, которая правильна (или я чего-то напутал?) с точки зрения типизации, ведь у нас определёны Int, Integer как экземпляры Encodable:
    
    decode s = 2
    
    То GHC вывалится с ошибкой:
    
    Could not deduce (Num a) from the context (Encodable a)
          arising from the literal `2' at DataProtocol.hs:76:11
        Possible fix:
          add (Num a) to the context of the type signature for `decode`
И не очень-то понятно что с этим делать.
linkReply

Comments:
[User Picture]From: permea_kra
2009-07-21 09:39 am (UTC)
2.
Possible fix:
add (Num a) to the context of the type signature for `decode`

decode :: (Encodable a, Num a) => B.ByteString -> a
потому что 2::(Num a => a), а вы объявляете возвращаемое значение только как Encodable

1)поковыряйте http://hackage.haskell.org/packages/archive/binary/
(Reply) (Thread)
From: braintrace
2009-07-21 09:42 am (UTC)
Хм... ок, а если я буду декодировать данные, тип которых не является экхемпляром Num? [Char] например.
(Reply) (Parent) (Thread)
[User Picture]From: permea_kra
2009-07-21 09:58 am (UTC)
lass Encodable a where
encode :: a -> B.ByteString
decode :: B.ByteString -> (a, B.ByteString)

Поковыряйте binary, его не дураки писали, там почти всё уже решили.

(Reply) (Parent) (Thread)
[User Picture]From: nponeccop
2009-07-21 12:41 pm (UTC)
Если протокол сложный, можете для decode использовать Text.ParserCombinators.Parsec
(Reply) (Thread)
[User Picture]From: _navi_
2009-07-21 05:01 pm (UTC)
советую почитать про Pickler Combinators, Ваня Веселов на SPbHUG докладывал, в принципе по презентации можно разобраться.
(Reply) (Thread)
From: ext_72902
2009-07-22 03:49 am (UTC)
А почему класс, а не тип данных?
(Reply) (Thread)