這是一個關于遍歷相互遞回資料型別的問題。我正在使用 Indexed Functor 為一堆相互遞回的資料型別建模 AST,如此處的要點所述。這足以滿足我的預期目的。
現在我需要用自上而下的資料流來轉換我的資料結構。這是在 Functor 的背景關系中提出的一個 SoF 問題,它表明代數的載體可以是一個函式,它允許在遍歷期間向下推資料。但是,我正在努力將這種技術與 Indexed Functor 一起使用。我認為我的資料型別需要更改,但我不確定如何更改。
這是一些說明我的問題的代碼。請注意,我不包括相互遞回型別或多個索引,因為我不需要它們來說明問題。
setDepth 應該將每個 (IntF n) 更改為 (IntF depth)。撰寫的函式不會進行型別檢查,因為種類 'AstIdx -> *' 不匹配 'Int -> Expr ix'。也許我遺漏了一些東西,但我看不出有一種方法可以在不放松 IxFunctor 中的 f 限制較少的情況下解決這個問題,但這似乎是錯誤的。
歡迎任何想法、建議或指點!
{-# LANGUAGE PolyKinds #-}
infixr 5 ~>
type f ~> g = forall i. f i -> g i
class IxFunctor (f :: (k -> *) -> k -> *) where
imap :: (a ~> b) -> (f a ~> f b)
-- Indexed Fix
newtype IxFix f ix = IxIn {ixout :: f (IxFix f) ix}
-- Fold
icata :: IxFunctor f => (f a ~> a) -> (IxFix f ~> a)
icata phi = phi . imap (icata phi) . ixout
-- Kinds of Ast
data AstIdx = ExprAst | TypeAst
-- AST
data ExprF (f :: AstIdx -> *) (ix :: AstIdx) where
IntF :: Int -> ExprF f ExprAst
AddF :: f ExprAst -> f ExprAst -> ExprF f ExprAst
type Expr = IxFix ExprF
instance IxFunctor ExprF where
imap f (IntF n) = IntF n
imap f (AddF a b) = AddF (f a) (f b)
-- Change (IntF n) to (IntF (n 1)).
add1 :: Expr ix -> Expr ix
add1 e = icata go e
where
go :: ExprF Expr ix -> Expr ix
go (IntF n) = IxIn (IntF (n 1))
go (AddF a b) = IxIn (AddF a b)
{-
-- Change (IntF n) to (IntF depth)
-- Doesn't type check
setDepth :: Expr ix -> Expr ix
setDepth e = icata ((flip go) 0) e
where
-- byDepthF :: TreeF a (Integer -> Tree Integer) -> Integer -> Tree Integer
-- byDepthF :: TreeF a (Integer -> Tree Integer) -> Integer -> Tree Integer ix
go :: ExprF (Int -> Expr ix) ix -> Int -> Expr ix
go (IntF n) d = IxIn (IntF d)
go (AddF a b) d = IxIn (AddF (a d) (b d))
-}
uj5u.com熱心網友回復:
我在這里假設您正在嘗試將每個IntF節點設定為其在樹中的深度(如byDepthF鏈接問題中的函式),而不是一些名為depth.
如果是這樣,我認為您可能正在尋找類似以下的內容:
newtype IntExpr ix = IntExpr { runIntExpr :: Int -> Expr ix }
setDepth :: Expr ix -> Expr ix
setDepth e = runIntExpr (icata go e) 0
where
go :: ExprF IntExpr ix -> IntExpr ix
go (IntF n) = IntExpr (\d -> IxIn (IntF d))
go (AddF a b) = IntExpr (\d -> IxIn (AddF (runIntExpr a (d 1)) (runIntExpr b (d 1)))
也就是說,您需要定義一個newtype作為索引的第一個型別引數的a ExprF,通過Int ->讀取器傳遞索引。剩下的只是包裝和解包。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/463068.html
