سؤال

أحاول أن أتعامل مع صندوق أدوات XML من Haskell (hxt) وأضرب جدارًا في مكان ما ، لأنني لا يبدو أنني أفهم الأسهم بالكامل كأداة حسابية.

إليكم مشكلتي ، التي كنت آمل أن أوضحها بشكل أفضل قليلاً باستخدام جلسة GHCI:

> let parse p = runLA (xread >>> p) "<root><a>foo</a><b>bar</b><c>baz</c></root>"
> :t parse
parse :: LA XmlTree b -> [b]

لذا فإن Parse هي وظيفة مساعدة صغيرة تنطبق على أي سهم أعطيه لمستند XML Trivial

<root>
  <a>foo</a>
  <b>bar</b>
  <c>baz</c>
</root>

أحدد وظيفة مساعد آخر ، هذه المرة لاستخراج النص أسفل العقدة باسم معين:

> let extract s = getChildren >>> isElem >>> hasName s >>> getChildren >>> getText 
> :t extract
extract :: (ArrowXml cat) =>
   String -> cat (Data.Tree.NTree.TypeDefs.NTree XNode) String
> parse (extract "a" &&& extract "b") -- extract two nodes' content.
[("foo","bar")]

بمساعدة هذه الوظيفة ، من السهل استخدام &&& combinator لإقران نص اثنين من العقد المختلفة ، ثم ، على سبيل المثال ، تمريره إلى مُنشئ ، مثل هذا:

> parse (extract "a" &&& extract "b" >>^ arr (\(a,b) -> (b,a))) 
[("bar","foo")]

الآن يأتي الجزء الذي لا أفهمه: أريد أن أعامل اليسار! extract المكالمات getChildren على عقدة الجذر مرتين. بدلاً من ذلك ، أود أن أسميها مرة واحدة فقط! لذلك أحصل أولاً على طفل عقدة الجذر

> let extract' s = hasName s >>> getChildren >>> getText
> :t extract'
extract' :: (ArrowXml cat) => String -> cat XmlTree String
> parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b"))
[]

لاحظ أنني حاولت إعادة طلب المكالمات ، على سبيل المثال ، Iselem ، إلخ. لمعرفة ما إذا كانت هذه هي المشكلة. ولكن كما هو الحال ، ليس لدي أي فكرة عن سبب عدم عمل هذا. يوجد سهم "تعليمي" على هاسكل ويكي والطريقة التي فهمتها ، ينبغي يكون من الممكن أن أفعل ما أريد أن أفعله بهذه الطريقة - أي استخدام &&& من أجل إقران نتائج الحسابين.

إنه يعمل أيضًا-ولكن فقط في بداية سلسلة السهم ، وليس في منتصف الطريق ، عندما يكون لدي بعض النتائج بالفعل ، أريد أن أبقي "مشتركًا". لدي شعور بأنني لا أكون قادرًا على لف رأسي حول الفرق في الأفكار بين تكوين الوظيفة العادية وتدوين السهم. سأكون ممتنا جدا لأي مؤشرات! (حتى لو كان الأمر مجرد بعض السهم العام الذي يمر بعمق أكثر قليلاً من Haskell-Wiki.)

شكرًا لك!

هل كانت مفيدة؟

المحلول

إذا قمت بتحويل السهم إلى (ثم من) نسخة حتمية ، فهذا يعمل كما هو متوقع:

> let extract' s = unlistA >>> hasName s >>> getChildren >>> getText
> parse (listA (getChildren >>> isElem) >>> (extract' "a" &&& extract' "b"))
[("foo","bar")]

هذا ليس مرضيًا حقًا ، ولا أستطيع أن أتذكر الجزء العلوي من رأسي لماذا (&&&) يتصرف بهذه الطريقة بسهم غير محدد (أنا شخصياً أستخدم proc/do الرموز لأي شيء أكثر تعقيدًا من هذا).


تحديث: يبدو أن هناك شيئًا غريبًا يحدث هنا runLA و xread. إذا كنت تستخدم runX و readString كل شيء يعمل كما هو متوقع:

> let xml = "<root><a>foo</a><b>bar</b><c>baz</c></root>"
> let parse p = runX (readString [] xml >>> p)
> let extract' s = getChildren >>> hasName s >>> getChildren >>> getText
> parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b"))
[("foo","bar")]

هذا يعني أنه يجب عليك تشغيل المحلل في IO موناد ، ولكن هناك مزايا لاستخدام runX على أي حال (رسائل خطأ أفضل ، وما إلى ذلك).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top