レンズを使用し始めていますが、今まで私が書いているコードベースの具体的な部分では使用できませんでした。私の目的は、既存のものの1つの中に新しいノードを追加することによって、Data.Tree
にあるようなバラのツリー構造を更新することです。それはそのようになりますので、そうするために、私は、それが一意のIDと各ノードを識別するために理にかなっていることを考えた:Haskellでレンズを使用してData.Treeに移動して要素を追加する
type MyTree = Tree Id
type Path = [Id]
addToTree :: MyTree -> MyTree -> Path -> MyTree
addToTree originalTree newNode path = undefined
機能addToTree
は、IDのパスに従うことによってoriginalTree
を横断し、追加する必要がありますそのレベルのnewNode
が更新されたツリー全体を返します。私はそれをゲッターにするのに問題はなかったが、私は手術で適切なレンズを見つけることができない。私が今まで持っているものだ
:
import Control.Lens
import Data.Tree
import Data.Tree.Lens
addToTree :: MyTree -> Path -> MyTree -> MyTree
addToTree tree path branch = tree & (traversalPath path) . branches %~ (branch:)
traversalPath :: (Foldable t, Applicative f, Contravariant f) => t Id -> (MyTree -> f MyTree) -> MyTree -> f MyTree
traversalPath = foldl (\acc id-> acc . childTraversal id) id
childTraversal :: (Indexable Int p, Applicative f) => Id -> p MyTree (f MyTree) -> MyTree -> f MyTree
childTraversal id = branches . traversed . withId id
withId :: (Choice p, Applicative f) => Id -> Optic' p f MyTree MyTree
withId id = filtered (\x -> rootLabel x == id)
しかし、それはとコンパイルに失敗します。
• No instance for (Contravariant Identity) arising from a use of ‘traversalPath’ • In the first argument of ‘(.)’, namely ‘(traversalPath path)’ In the first argument of ‘(%~)’, namely ‘(traversalPath path) . branches’ In the second argument of ‘(&)’, namely ‘(traversalPath path) . branches %~ (branch :)’
ありがとう!
マイナーな説明: 'path'の' originalTree'部分のルートですか? – duplode
私は擬似実装中にそれをパスに含めませんでしたが、それがそこにあることは理にかなっています。私ははいと言うだろう。 – Jesuspc
'Contravariant'は取得するためのもので、設定するには' cmap'を使用しないでください。 'Contravariant'制約を' traversalPath'から削除してください。 – Gurkenglas