I'm just learning a haskell and seems like all is good even scary monads are not a big deal for me. But I can't get to real practiacal stuff at all.
My first practical task for haskell I choosed as follows:
Given a JSON describing some binary file's format to parse that file.
JSON has some deeply nested structure with lists of assocoative lists (dictionaries) of lists etc with endpoints as numbers or strings.
So first of all I want to be able to map other those endpoints (to have functor class for jsons data) converting some strings to numbers in particular. Also it would be nice to be able to fold all those endpoints as well.
I came up with some python code easily. But can't go any far with haskell.
So what your suggestions for implementing things in haskell? It really would be nice to hear some advise for solutions using libraries to greatest extent and not handwrite all the stuff from scratch.
Thanks in advance!
example of what I have in python
Some helper functions:
islist = lambda l: isinstance(l, collections.Iterable) and not isinstance(l, (str, bytes))
isdict = lambda d: isinstance(d, collections.Mapping)
isiter = lambda i: islist(i) or isdict(i)
i = d.items()
i = enumerate(d)
def nested_iter(nested, f = lambda *args: None):
for key, value in iterable(nested):
if not isiter(value):
yield key, value
yield from nested_iter(value, f)
def list_from_num(d, k):
if type(d[k]) == int:
d[k] = [k]*d[k]
def nest_dicts(defs, d, k):
if d[k] in defs.keys():
d[k] = deepcopy(defs[d[k]])
list(nested_iter(d[k], partial(nest_dicts, defs)))
list(nested_iter(typedef, partial(nest_dicts, typedef)))
Well this is my solution. It uses Control.Lens, Data.Aeson.Lens, Control.Lens.Plated
One can use transform from Uniplate or Lens.Plated to transform values.
for example to substitute each number with list of key values of length of that number:
n2k :: T.Text -> Value -> Value --import qualified Data.Text as T n2k s (Number x) | isInteger x = case toBoundedInteger x of Just n -> Array (V.replicate n (String s)) -- import qualified Data.Vector as V _ -> Number x | otherwise = Number x n2k _ v = v f (Object o) = Object $ imap n2k o --imap from Data.Map.Lens f x = x j2 = transform f j --transform JSON j using function f
to substitute string with data with same key:
-- o is hashmap where we are looking for keys to substitute strings h (String s) = fromMaybe (String s) (H.lookup s o) --import qualified Data.HashMap.Lazy as H h x = x j2 = transform h j
just get all numbers into list:
l = [x | Number x <- universe j]