我只是学习一个haskell,看起来一切都很好,即使可怕的monad对我来说也不是什么大问题。但我根本无法获得真实的实际内容。
我选择的第一个haskell实际任务如下: 给定一个JSON描述一些二进制文件的格式来解析该文件。
JSON有一些深层嵌套的结构,其中包含列表的关联列表(字典)列表,其中端点为数字或字符串。 首先,我希望能够映射其他那些端点(为jsons数据设置functor类),特别是将一些字符串转换为数字。同样能够折叠所有这些端点也是很好的。
我很容易想出一些python代码。但是与haskell无关。 那么你对haskell实现的建议是什么?听到一些最大程度上使用库的解决方案的建议真的很高兴,而不是从头开始编写所有东西。
提前致谢!
加入--- 我在python中的例子
一些辅助函数:
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)
def iterable(d):
if isdict(d):
i = d.items()
elif islist(d):
i = enumerate(d)
else:
raise ValueError
return i
迭代嵌套json数据的迭代器:
def nested_iter(nested, f = lambda *args: None):
for key, value in iterable(nested):
if not isiter(value):
f(nested, key)
yield key, value
else:
yield from nested_iter(value, f)
现在我可以用键列表替换一些数字:
def list_from_num(d, k):
if type(d[k]) == int:
d[k] = [k]*d[k]
list(nested_iter(typedef, list_from_num))
或者我可以用一些其他具有相同键名的嵌套数据替换某些字符串
def nest_dicts(defs, d, k):
if d[k] in defs.keys():
d[k] = deepcopy(defs[d[k]])
if isiter(d[k]):
list(nested_iter(d[k], partial(nest_dicts, defs)))
list(nested_iter(typedef, partial(nest_dicts, typedef)))
或者可以展平数据
list(nested_iter(d))
解析二进制文件有点进化,但它只不过是向迭代器传递一个函数
答案 0 :(得分:0)
这是我的解决方案。 它使用Control.Lens,Data.Aeson.Lens,Control.Lens.Plated
可以使用Uniplate或Lens.Plated转换来转换值。
例如用每个数字替换该数字长度的键值列表:
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
用具有相同键的数据替换字符串:
-- 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
将所有数字都列入清单:
l = [x | Number x <- universe j]