Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1.  converting a json encoded radix tree to a        haskell data type
      (Adam Flott)
   2. Re:  converting a json encoded radix tree to a haskell data
      type (Karl Voelker)
   3. Re:  converting a json encoded radix tree to a haskell data
      type (Adam Flott)
   4. Re:  converting a json encoded radix tree to a haskell data
      type (David McBride)
   5. Re:  converting a json encoded radix tree to a haskell data
      type (Adam Flott)


----------------------------------------------------------------------

Message: 1
Date: Thu, 27 Aug 2015 11:04:38 -0400
From: Adam Flott <[email protected]>
To: [email protected]
Subject: [Haskell-beginners] converting a json encoded radix tree to a
        haskell data type
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8

I'm having trouble converting a JSON encoded Radix tree into a Haskell
data type[1]. I've tried numerous ways to get the FromJSON instances to
handle all cases, but failing miserably.

[1] unfortunately these type layouts are unchangeable as they are auto
generated types from Thrift


Here is a stripped down version of what I'm working with. For the JSON
file, all keys are unknown at parse time. I only know that a key will be
a string and it's value will be another JSON object or a JSON array of
fixed length.

Any help is appreciated.


-- radix.hs --
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}

import Control.Monad (mzero)
import Data.Int
import Data.Typeable

import Data.Aeson
import qualified Data.ByteString.Lazy as BL
import Data.Text.Lazy as TL
import qualified Data.Vector as V

data Things = MkThings {
  thing   :: TL.Text,
  times :: ThingTimes
  } deriving (Show, Eq, Typeable)

data ThingTimes = MkThingtimes {
  ml :: V.Vector Times
  } deriving (Show, Eq, Typeable)

data Times = MkTimes {
  t1 :: Maybe Int32,
  t2 :: Maybe Int32
  } deriving (Show, Eq, Typeable)

instance FromJSON (V.Vector Things) where
  parseJSON _ = return V.empty

decodeRadix ::BL.ByteString -> Either String (V.Vector Things)
decodeRadix = eitherDecode

main :: IO ()
main = do
  j <- BL.readFile "radix.json"
  case decodeRadix j of
    Left err -> error err
    Right r -> print r
-- radix.hs --

-- radix.json --
{
    "a" : {
        "b" : [ 1, 2 ],
        "c" : {
            "d" : [ 3, null ]
        }
    },
    "a2" : { "b2" : [ 4, 5 ] }
}
-- radix.json --



------------------------------

Message: 2
Date: Thu, 27 Aug 2015 08:18:45 -0700
From: Karl Voelker <[email protected]>
To: [email protected]
Subject: Re: [Haskell-beginners] converting a json encoded radix tree
        to a haskell data type
Message-ID:
        <1440688725.3956294.367671881.7f4d1...@webmail.messagingengine.com>
Content-Type: text/plain

On Thu, Aug 27, 2015, at 08:04 AM, Adam Flott wrote:
> data Things = MkThings {
>   thing   :: TL.Text,
>   times :: ThingTimes
>   } deriving (Show, Eq, Typeable)
> 
> data ThingTimes = MkThingtimes {
>   ml :: V.Vector Times
>   } deriving (Show, Eq, Typeable)
> 
> data Times = MkTimes {
>   t1 :: Maybe Int32,
>   t2 :: Maybe Int32
>   } deriving (Show, Eq, Typeable)
> 
> -- radix.json --
> {
>     "a" : {
>         "b" : [ 1, 2 ],
>         "c" : {
>             "d" : [ 3, null ]
>         }
>     },
>     "a2" : { "b2" : [ 4, 5 ] }
> }
> -- radix.json --

It looks like your input file has Things nested inside Things, but your
data types don't allow for that. Is that intentional? What value is that
example input supposed to parse to?

-Karl


------------------------------

Message: 3
Date: Thu, 27 Aug 2015 11:30:36 -0400
From: Adam Flott <[email protected]>
To: [email protected]
Subject: Re: [Haskell-beginners] converting a json encoded radix tree
        to a haskell data type
Message-ID: <[email protected]>
Content-Type: text/plain; charset=windows-1252

On 08/27/2015 11:18 AM, Karl Voelker wrote:
> On Thu, Aug 27, 2015, at 08:04 AM, Adam Flott wrote:
>> data Things = MkThings {
>>   thing   :: TL.Text,
>>   times :: ThingTimes
>>   } deriving (Show, Eq, Typeable)
>>
>> data ThingTimes = MkThingtimes {
>>   ml :: V.Vector Times
>>   } deriving (Show, Eq, Typeable)
>>
>> data Times = MkTimes {
>>   t1 :: Maybe Int32,
>>   t2 :: Maybe Int32
>>   } deriving (Show, Eq, Typeable)
>>
>> -- radix.json --
>> {
>>     "a" : {
>>         "b" : [ 1, 2 ],
>>         "c" : {
>>             "d" : [ 3, null ]
>>         }
>>     },
>>     "a2" : { "b2" : [ 4, 5 ] }
>> }
>> -- radix.json --
> It looks like your input file has Things nested inside Things, but your
> data types don't allow for that. Is that intentional? What value is that
> example input supposed to parse to?

Vector [
    MkThings "ab" (MkThingTimes (Vector [ Just 1, Just 2 ])),
    MkThings "abcd" (MkThingsTimes (Vector [ Just 3, Nothing))
    MkThings "a2b2" (MkThingTimes (Vector [ Just 4, Just 5 ])) ]


------------------------------

Message: 4
Date: Thu, 27 Aug 2015 13:45:54 -0400
From: David McBride <[email protected]>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Subject: Re: [Haskell-beginners] converting a json encoded radix tree
        to a haskell data type
Message-ID:
        <can+tr43vecmqmffivmof8en3kppocchzrfecxos57ezu8y8...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

I was trying this but ran into a bit of trouble.  Are you super attached to
that data structure?  I would expect a radix tree as you've described it to
look more like this:

data RadixTree = Node [(Text, RadixTree)] | Leaf Times
data Times = Times (Maybe Int) (Maybe Int)

In which case it is much easier to write the json instances.  From there
you shouldn't have too much of a problem writing a recursive function to do
the rest, without dealing with all the aeson stuff at the same time.
Here's what I ended up with (I think it could be cleaned up a bit).

import Control.Monad
import Data.Text as T
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.Vector as V hiding (mapM)

data RadixTree = Node [(Text, RadixTree)] | Leaf Times deriving Show
data Times = Times (Maybe Int) (Maybe Int) deriving Show

instance FromJSON RadixTree where
  parseJSON (Object o) = do
    let els = HM.toList o
    contents <- mapM (\(t,v) -> do v' <- parseJSON v; return (t, v'))
(HM.toList o)
    return $ Node contents
  parseJSON a@(Array _) = Leaf <$> parseJSON a
  parseJSON _ = mzero

instance FromJSON Times where
  parseJSON (Array v) | (V.length v) >= 2 =
    let v0 = v V.! 0
        v1 = v V.! 1
    in Times <$> parseJSON v0 <*> parseJSON v1
  parseJSON _ = mzero

{-
tree2things :: RadixTree -> [(Text, (Maybe Int, Maybe Int))]
tree2things (Node xs) = _
tree2things (Leaf t) = _
-}

On Thu, Aug 27, 2015 at 11:30 AM, Adam Flott <[email protected]> wrote:

> On 08/27/2015 11:18 AM, Karl Voelker wrote:
> > On Thu, Aug 27, 2015, at 08:04 AM, Adam Flott wrote:
> >> data Things = MkThings {
> >>   thing   :: TL.Text,
> >>   times :: ThingTimes
> >>   } deriving (Show, Eq, Typeable)
> >>
> >> data ThingTimes = MkThingtimes {
> >>   ml :: V.Vector Times
> >>   } deriving (Show, Eq, Typeable)
> >>
> >> data Times = MkTimes {
> >>   t1 :: Maybe Int32,
> >>   t2 :: Maybe Int32
> >>   } deriving (Show, Eq, Typeable)
> >>
> >> -- radix.json --
> >> {
> >>     "a" : {
> >>         "b" : [ 1, 2 ],
> >>         "c" : {
> >>             "d" : [ 3, null ]
> >>         }
> >>     },
> >>     "a2" : { "b2" : [ 4, 5 ] }
> >> }
> >> -- radix.json --
> > It looks like your input file has Things nested inside Things, but your
> > data types don't allow for that. Is that intentional? What value is that
> > example input supposed to parse to?
>
> Vector [
>     MkThings "ab" (MkThingTimes (Vector [ Just 1, Just 2 ])),
>     MkThings "abcd" (MkThingsTimes (Vector [ Just 3, Nothing))
>     MkThings "a2b2" (MkThingTimes (Vector [ Just 4, Just 5 ])) ]
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://mail.haskell.org/pipermail/beginners/attachments/20150827/5d4b39ef/attachment-0001.html>

------------------------------

Message: 5
Date: Thu, 27 Aug 2015 16:31:25 -0400
From: Adam Flott <[email protected]>
To: [email protected]
Subject: Re: [Haskell-beginners] converting a json encoded radix tree
        to a haskell data type
Message-ID: <[email protected]>
Content-Type: text/plain; charset=windows-1252

I am attached to the data structure as it's what our Thrift message
spits out and has to be mapped that way for the down stream consumers.


On 08/27/2015 01:45 PM, David McBride wrote:
> I was trying this but ran into a bit of trouble.  Are you super
> attached to that data structure?  I would expect a radix tree as
> you've described it to look more like this:
>
> data RadixTree = Node [(Text, RadixTree)] | Leaf Times
> data Times = Times (Maybe Int) (Maybe Int)
>
> In which case it is much easier to write the json instances.  From
> there you shouldn't have too much of a problem writing a recursive
> function to do the rest, without dealing with all the aeson stuff at
> the same time.  Here's what I ended up with (I think it could be
> cleaned up a bit).
>
> import Control.Monad
> import Data.Text as T
> import Data.Aeson
> import Data.HashMap.Strict as HM
> import Data.Vector as V hiding (mapM)
>
> data RadixTree = Node [(Text, RadixTree)] | Leaf Times deriving Show
> data Times = Times (Maybe Int) (Maybe Int) deriving Show
>
> instance FromJSON RadixTree where
>   parseJSON (Object o) = do
>     let els = HM.toList o
>     contents <- mapM (\(t,v) -> do v' <- parseJSON v; return (t, v'))
> (HM.toList o)
>     return $ Node contents
>   parseJSON a@(Array _) = Leaf <$> parseJSON a
>   parseJSON _ = mzero
>
> instance FromJSON Times where
>   parseJSON (Array v) | (V.length v) >= 2 =
>     let v0 = v V.! 0
>         v1 = v V.! 1
>     in Times <$> parseJSON v0 <*> parseJSON v1
>   parseJSON _ = mzero
>
> {-
> tree2things :: RadixTree -> [(Text, (Maybe Int, Maybe Int))]
> tree2things (Node xs) = _
> tree2things (Leaf t) = _
> -}
>
> On Thu, Aug 27, 2015 at 11:30 AM, Adam Flott <[email protected]
> <mailto:[email protected]>> wrote:
>
>     On 08/27/2015 11:18 AM, Karl Voelker wrote:
>     > On Thu, Aug 27, 2015, at 08:04 AM, Adam Flott wrote:
>     >> data Things = MkThings {
>     >>   thing   :: TL.Text,
>     >>   times :: ThingTimes
>     >>   } deriving (Show, Eq, Typeable)
>     >>
>     >> data ThingTimes = MkThingtimes {
>     >>   ml :: V.Vector Times
>     >>   } deriving (Show, Eq, Typeable)
>     >>
>     >> data Times = MkTimes {
>     >>   t1 :: Maybe Int32,
>     >>   t2 :: Maybe Int32
>     >>   } deriving (Show, Eq, Typeable)
>     >>
>     >> -- radix.json --
>     >> {
>     >>     "a" : {
>     >>         "b" : [ 1, 2 ],
>     >>         "c" : {
>     >>             "d" : [ 3, null ]
>     >>         }
>     >>     },
>     >>     "a2" : { "b2" : [ 4, 5 ] }
>     >> }
>     >> -- radix.json --
>     > It looks like your input file has Things nested inside Things,
>     but your
>     > data types don't allow for that. Is that intentional? What value
>     is that
>     > example input supposed to parse to?
>
>     Vector [
>         MkThings "ab" (MkThingTimes (Vector [ Just 1, Just 2 ])),
>         MkThings "abcd" (MkThingsTimes (Vector [ Just 3, Nothing))
>         MkThings "a2b2" (MkThingTimes (Vector [ Just 4, Just 5 ])) ]
>     _______________________________________________
>     Beginners mailing list
>     [email protected] <mailto:[email protected]>
>     http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners



------------------------------

Subject: Digest Footer

_______________________________________________
Beginners mailing list
[email protected]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


------------------------------

End of Beginners Digest, Vol 86, Issue 20
*****************************************

Reply via email to