在 Elm 中,我如何遍历地图?

In Elm, how can I iterate over a map?

我对 Elm 和一般的 FP 还很陌生,但我对 Haskell 有一点经验。如果我在这里使用的术语不正确,请原谅我。

我正在尝试做一些类似 XSLT 的事情,替换 XML 中的模式以将其转换为 HTML。

我有一张模式图和替换图。我不太确定最好的数据结构是什么,但我正在尝试类似的东西:

type alias Replacement = { pattern: String, replacement: String }

type ReplacementMap = List Replacement

replacementMap : ReplacementMap
replacementMap = [ { pattern: "<head>", replacement: "<h1>" },
                   { pattern: "<lg>", replacement: "<ul>" },
                   { pattern: "<l>", replacement: "<li>" } ]

然后我会做类似的事情:

type alias Xml = String

replacePat : Xml -> Html
replacePat pat repl = replace Regex.All (regex pat) (\_ -> repl)

将 XML 标签 headlgl 替换为它们的 HTML 等价物。我还不知道如何做的是遍历我的 replacementMap,用它的替换替换每个模式。或者也许有更好的方法来完全做到这一点?

首先,这是一个工作示例:

import Html exposing (text)
import Regex as R

type alias Replacement = { pattern: R.Regex, replacement: String }
type alias ReplacementMap = List Replacement
type alias Xml = String

main =
  let
    replacements =
      [ { pattern = R.regex "<head>", replacement = "<h1>" }
      , { pattern = R.regex "</head>", replacement = "</h1>" }
      , { pattern = R.regex "<lg>", replacement = "<ul>" }
      , { pattern = R.regex "</lg>", replacement = "</ul>" }
      , { pattern = R.regex "<l>", replacement = "<li>" }
      , { pattern = R.regex "</l>", replacement = "</li>" }
      ]

    example = "<head>Foo</head>"
  in    
    text (replacePat example replacements)

replace : Replacement -> Xml -> Xml
replace replacement xml =
  R.replace R.All replacement.pattern (always replacement.replacement) xml

replacePat : Xml -> ReplacementMap -> String
replacePat xml rmap =
  List.foldl replace xml rmap

要解决问题,首先要考虑您的输入和输出:

输入: List 替换模式和 String XML。

输出: HTML

String

当您有一个集合,例如 List,并且您想要得到一个东西(例如 String),这表明您需要执行某种操作减少:你要从多到一。减少 List 通常意味着您将弃牌(foldlfoldr)。

foldr 遍历一个列表,将提供的函数(在本例中为 replace)应用于列表中的一个项目以及应用该函数的前一个结果;除了第一次迭代,在此期间使用起始值(在您的情况下为初始 XML )。随着迭代的继续,这会导致...串联效应。最后返回最后一次应用函数的结果作为最终值。

也就是说,List.foldl replace xml rmap相当于一堆嵌套的函数应用(调用):

replace 
  { pattern = R.regex "<lg>", replacement = "<ul>" } 
  (replace 
     { pattern = R.regex "</head>", replacement = "</h1>" } 
     (replace 
        { pattern = R.regex "<head>", replacement = "<h1>" }                    
        "<head>Foo</head>"))

...等等。