我是Elm的新手,到目前为止我真的很喜欢它,但我遇到了一个我似乎无法理解的问题。
例如,我有一个Html DOM
div []
[ h1 [] [text "Headline 1"]
, p [] [text "Some text"]
, h2 [] [text "Headline 2"]
]
我想在每个h1-6元素中添加a-link,这样就可以把它转换成像这样的东西(保持简单)
div []
[ h1 [] [ text "Headline 1"
, [a [name "headline"] [text "#"]
]
, p [] [text "Some text"]
, h2 [] [text "Headline 2"
, [a [name "headline"] [text "#"]
]
]
从概念上讲,这并不是很难。查看DOM,如果元素是h1-6,则添加一个a-link作为子元素。然而,我对Elm的理解还不够好,无法让它正常工作。
这是我到目前为止一直在尝试的。
transform : Html a -> Html a
transform node =
-- check if the tag is h1-h6
case node.tag of
-- add a-link to h1 children
"h1" -> { node | children = (a [name "headline"] [text "#") :: node.children }
"h2" -> { node | children = (a [name "headline"] [text "#") :: node.children }
-- do this for all nodes in the tree
_ -> { node | children = List.map transform node.children }
这不管用。
The type annotation for `transform` does not match its definition.
40| transform : Html a -> Html a
^^^^^^^^^^^^^^^^
The type annotation is saying:
VirtualDom.Node a -> VirtualDom.Node a
But I am inferring that the definition has this type:
{ b | tag : String, children : List (Html a) }
-> { b | children : List (Html a), tag : String }
我知道我不能做node.tag
,因为泛型类型a
可能没有这个字段。它就不是类型安全的。例如,文本节点没有标记字段,但仍然是Html.Html a
的实例。
> text "Hello World"
{ type = "text", text = "Hello World" } : Html.Html a
我的问题是,我如何才能做到这一点?我能这么做吗?还是说我不应该这么做?
发布于 2016-08-05 19:42:40
无法修改Html msg
类型的现有值。
它们是最终的内部结构,由Virtual DOM呈现给实际的HTML节点作为程序的输出。
Html msg
是VirtualDom.Node a
的别名
您正试图将它们用作记录,但这只是一个JavaScript对象。
Elm REPL在这里输出抽象数据结构的字符串表示:
> text "Hello World"
{ type = "text", text = "Hello World" } : Html.Html a -- not a record
与其尝试转换Html msg -> Html msg
,不如尝试如下所示:
-- Input example: [ "#", "http://google.com/", "http://package.elm-lang.org/" ]
linksView : List String -> Html msg
linksView links =
links
|> List.map (\link -> a [ href link ] [ text link ])
|> div [] -- Expected output: <div> with thre links
发布于 2016-08-05 19:48:52
在Elm中,Html a
实际上只用作输出。您永远不会以transform
函数尝试的方式将其用作输入。
通过创建一个模型来描述您的域,然后将其传递给一个view
函数来呈现html,您将获得更好的服务。
type alias Article =
{ priority : Priority
, headline : String
, body : String
}
type alias Model =
List Article
type Priority = First | Second
然后,您的视图可能如下所示:
view : Model -> Html msg
view =
div [] << List.map viewArticle
viewArticle : Article -> Html msg
viewArticle article =
let
priorityTag =
case article.priority of
First -> h1
Second -> h2
in
div []
[ priorityTag []
[ text article.headline
, a [ name "headline" ] [ text "#" ]
]
, p [] [ text article.body ]
]
https://stackoverflow.com/questions/38787764
复制相似问题