gpt4 book ai didi

haskell - 在已经是 Functor 的数据类型上使用 `Fix` 的递归方案?

转载 作者:行者123 更新时间:2023-12-04 06:05:19 25 4
gpt4 key购买 nike

仍在使用我的文本编辑器 Rasa .

目前我正在构建用于跟踪视口(viewport)/拆分的系统(类似于 vim 拆分)。对我来说,将这个结构表示为一棵树似乎很自然:

data Dir = Hor
| Vert
deriving (Show)

data Window a =
Split Dir SplitInfo (Window a) (Window a)
| Single ViewInfo a
deriving (Show, Functor, Traversable, Foldable)

这很好用,我存储了我的 View s 在树中,然后我可以遍历/fmap 来改变它们,它也与镜头包非常吻合!

我一直在学习 Recursion Schemes最近,这似乎对他们来说是一个合适的用例,因为树是一个递归数据结构。

我设法弄清楚它足以构建 Fixpoint 版本:
data WindowF a r =
Split Dir SplitInfo r r
| Single ViewInfo a
deriving (Show, Functor)

type Window a = Fix (WindowF a)

然而,现在 Functor 实例被 r 用完了。 ;

我尝试了一些变体
deriving instance Functor Window

但它令人窒息,因为 window 是一个类型的同义词。

和:
newtype Window a = Window (Fix (WindowF a)) deriving Functor

这也失败了;
• Couldn't match kind ‘* -> *’ with ‘*’
arising from the first field of ‘Window’ (type ‘Fix (WindowF a)’)
• When deriving the instance for (Functor Window)
  • 是否仍然可以在 a 上定义 fmap/traverse ?或者我需要使用 recursion-schemes 来执行这些操作吗?原始人?我要实现双仿函数吗?实例实现会是什么样子?

  • 其余类型为 here ,该项目无法编译,因为我没有合适的 Functor 实例用于 Window...

    谢谢!!

    最佳答案

    经过大量的努力,我得出的结论是,更好的选择是定义两种数据类型;具有您想要的属性的标准数据类型(在本例中为 Bifunctor)和可以定义的递归 Functor 数据类型Base , RecursiveCorecursive的实例。

    这是它的样子:

    {-# language DeriveFunctor, DeriveTraversable, TypeFamilies  #-}

    import Data.Typeable
    import Data.Bifunctor
    import Data.Functor.Foldable

    data BiTree b l =
    Branch b (BiTree b l) (BiTree b l)
    | Leaf l
    deriving (Show, Typeable, Functor, Traversable, Foldable)

    instance Bifunctor BiTree where
    bimap _ g (Leaf x) = Leaf (g x)
    bimap f g (Branch b l r) = Branch (f b) (bimap f g l) (bimap f g r)

    data BiTreeF b l r =
    BranchF b r r
    | LeafF l
    deriving (Show, Functor, Typeable)

    type instance Base (BiTree a b) = BiTreeF a b
    instance Recursive (BiTree a b) where
    project (Leaf x) = LeafF x
    project (Branch s l r) = BranchF s l r

    instance Corecursive (BiTree a b) where
    embed (BranchF sp x xs) = Branch sp x xs
    embed (LeafF x) = Leaf x

    您现在可以像往常一样在整个代码中使用您的基本类型(BiTree);当您决定使用递归方案时,您只需要记住在解包时使用构造函数的“F”版本:
    anyActiveWindows :: Window -> Bool
    anyActiveWindows = cata alg
    where alg (LeafF vw) = vw^.active
    alg (BranchF _ l r) = l || r

    请注意,如果您最终重建一组窗口,您仍将使用 = 右侧的非 F 版本。 .

    我为我的场景定义了以下内容,效果很好;我两个都有 FunctorBifunctor对于 Window如我所愿,甚至不使用新类型:
    type Window = BiTree Split View

    data SplitRule =
    Percentage Double
    | FromStart Int
    | FromEnd Int
    deriving (Show)

    data Dir = Hor
    | Vert
    deriving (Show)

    data Split = Split
    { _dir :: Dir
    , _splitRule :: SplitRule
    } deriving (Show)

    makeLenses ''Split

    data View = View
    { _active :: Bool
    , _bufIndex :: Int
    } deriving (Show)

    makeLenses ''View

    关于haskell - 在已经是 Functor 的数据类型上使用 `Fix` 的递归方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41524960/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com