• ? code Haskell typefun
    про категории и регионы, т.е. тот пост, что был днём ранее, в итоге у меня получилось следующее:
    
    [там внизу вопрос ещё будет про type families и type classes, так что если интересно мне помочь, то всю эту писанину можно и пропустить]
    
    A.hs:
    {-# LANGUAGE UndecidableInstances #-}
    -- Вариант для чистого преобразования
    type CanReleasePure s g = CanRelease s g IO
    
    -- Правило позволяющее определить свой порядок
    type family IsAncestor a b (c :: * -> *) :: Bool
    
    -- Правило описывающее поведения "начального" и "терминального" элементов
    type family CanRelease s g (m :: * -> *) where
      CanRelease G x y = True
      CanRelease x V y = True
      CanRelease a b c  = IsAncestor a b c
    
    B.hs: -- тут собственно вводится мой трансформер
    
    -- Правило для спуска по монадному стеку и проверка
    type family IsAncestor2 a (m :: * -> *) :: Bool where
       IsAncestor2 a IO = False
       IsAncestor2 a (R m s) = a == s || IsAncestor a m
    
    -- Правило проверяющее, что можно будет кастовать только к
    -- только внешнему типу (можно былоб убрать, если в type family 
    -- в A.hs добавить Constraint
    type instance IsAncestor s g (R m s') = (g == s') || IsAncestor2 s (R m s')
    ---------------------------------------------------------------------------
    
    В общем-то то неплохо, хотя и замучено, пользователь библиотеки,
    конечно весь этот ад не увидит, в его распоряжении будет только
    
    CanReleasePure a b
    ну и функции это использующие:
    
    release :: CanReleasePure a b ~ True => S a c -> S b c
    releaseM :: (MonadR m, CanRelease a (Region m) m ~ True) => S a c -> m (S (Region m) c
    -----------------------------------------------------------------------------
    
    Так вот, всю эту радость можно реализовать и с помощью тайп классов,
    тогда констрейн будет выглядеть просто как CanRelease .. без ~ True,
    вопрос, тогда стоит что выбирать?

Replies (8)

  • @qnikst, UPD.
    type family IsAncestor2 a (m :: -> ) :: Bool where
    IsAncestor2 a (R m s) = a == s || IsAncestor a m
    IsAncestor2 a m = False
  • @qnikst, А почему нельзя, например, просто так gist.github.com сделать?
  • @klapaucius, а как я выражу что для R (R (R IO s0) s1) s2 a у меня:
    V < s0 <= s1 <= s2 < G
    V < a < G
    где там где <= можно сделать монадическое преобразование, а где < — чистое?
  • @klapaucius, аа это про то что не писать ~ True — это да, можно
  • @klapaucius, тут больше интересен вопрос какой из методов предпочтитеььнее
  • @qnikst, В смысле, что лучше — тайплевел пролог на классах типов или семейства типов — в более широком контексте? Проблема в том, что там всегда какие-то нюансы всплывают, так что пока не попробуешь — не узнаешь. Т.е. можно решить только написав два прототипа разными способами.
  • @klapaucius, я боюсь чо эти ньюансы выползут только в реальной программе (в смысле программе либу использующей) поэтому спрашивал можно какие-то общие рекомендации есть
  • @qnikst, эти ньюансы выползут только в реальной программеДа, так и будет.
    какие-то общие рекомендации естьДумаю нет.