Можем ли мы сохранить Observable Sharing для нескольких вызовов reifyGraph? - PullRequest
0 голосов
/ 13 марта 2019

Я работаю над инструментом анализа / преобразования языка, который позволяет распространять изменения в AST через серию проходов преобразования.Чтобы сделать API более привлекательным, я бы хотел связать серию вызовов reifyGraph во времени.

Для начала, шаблон:

import Data.Reify
import Data.Reify.Graph
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
import Control.Monad.IO.Class

Некоторая простота использования кода, который позволяет мне получить экземпляр MuRef с классами, которые мы находим в схемах рекурсии:

newtype MuReify a = MuR { getRec :: a }

type instance Base (MuReify a) = Base a

instance (Recursive t, Traversable (Base t)) => MuRef (MuReify t) where
  type DeRef (MuReify t) = Base t

  mapDeRef f = traverse (f . MuR) . project . getRec

reifyMuRef :: (Recursive s, Traversable (Base s)) => s -> IO (Graph (Base s))
reifyMuRef = reifyGraph . MuR

Используемый мной игрушечный язык, взятый непосредственно из документации по схемам рекурсии:

data Expr a
    = Lit a
    | Add (Expr a) (Expr a)
    | Expr a :* [Expr a]
  deriving (Show)

makeBaseFunctor ''Expr

deriving instance (Show a, Show f) => Show (ExprF a f)

Учитывая все вышеизложенное, я хочу иметь возможность связать серию вариантов, чтобы я мограсскажите, какие термины распределяются между звонками, а также в пределах определенного графика.

У меня есть небольшой фрагмент, который помогает продемонстрировать, что я хотел бы:

main :: IO ()
main = do
  let l3 = Lit 3
      l5 = Lit 5
      add = Add l3 add 
      mul = l5 :* [Lit 2, add] 
      foo = Add add mul
      bar = Add foo l3
  print =<< traverse reifyMuRef [bar,mul,foo]

Когда вы запустите вышеприведенное, вы получите (без дополнительного форматирования):

bar = let [(1,AddF 2 4)
          ,(2,AddF 3 5)
          ,(3,AddF 4 3)
          ,(4,LitF 3)]
          ,(5,6 :*$ [7,3])
          ,(6,LitF 5) 
          ,(7,LitF 2)]
      in 1


mul = let [(1,2 :*$ [3,4])
          ,(2,LitF 5)
          ,(3,LitF 2)
          ,(4,AddF 5 4)
          ,(5,LitF 3)]
      in 1

foo = let [(1,AddF 2 4),
          ,(2,AddF 3 2)
          ,(3,LitF 3)
          ,(4,5 :*$ [6,2])
          ,(5,LitF 5)
          ,(6,LitF 2)] 
      in 1

Заметьте, как, хотя существует один экземпляр, где мы определяем Lit 3, соответствующий термин LitF 3 обнаруживается с разными индексами в каждом из графиков?

За исключением полноценного анализа графа, есть ли какой-нибудь способ для меня выяснить, какие термины эквивалентны во всех выражениях?

...