Ilya
начал переписывать тайпалиас на ньютайп + LibMonad тайпкласс и вылезла интересная проблема https://gist.github.com/SPY/ff745898629800f967949cd14ead1ed5
Ilya
раньше во вспомогательных тайпклассах я использовал конкретный тайпнейм и по этому тайпчекер всё понимал, но теперь когда всё ушло в констрейнты type OutType перестал чекаться, потому что для монадного инстанса он слишком общий
Ilya
это как-то можно победить? какой-нибудь волшебный экстеншен который позволит констренты в дефинишен типа например добавить или ещё что-то такое
Ilya
выглядит так, что мне нужно что-то типа этого https://ghc.haskell.org/trac/ghc/ticket/4259
Dmitry
m (Proxy t) перекрывается с Loc t. Надо как-то их разделять. У t кайнд Type в обоих случаях? Нельзя какой-нибудь специальный кайнд завести?
Dmitry
Можно еще добавить в класс параметр (isLoc :: Bool). И различать по 'True или 'False (скорее всего - вспомогательный класс сделать).
Alexander
Alexander
хотя кому и Applicative конфиг
Ilya
Ilya
пытаюсь запилить на мультипарам тайпклассах, но пока что-то тяжко идет
Dmitry
Вспомогательный класс с доп. параметром с кайндом Bool.
Dmitry
А у тебя еще будут инстансы или только два? А то можно закрытую type family использовать. Там ничего не перекроется.
Ilya
я вынес в закрытую тайпфемили, но там всё ещё сложнее оказалось 🙂
Dmitry
Почему?
Ilya
там не очевидно что FunGenMonad m из констрейнта для produce мапится на FunGenMonad m из заголовка инстанса
Ilya
и получается что бы их унифицировать всё равно надо выносить это на уровень тайпкласса
Ilya
хотя загнался, это другая проблема
Ilya
ща вспомню почему не работала закрытая тайпфемили
Dmitry
Что-то такое должно работать наверное (не компилировал) https://gist.github.com/odr/44e6f17e3bc4616b2d055ceb2ee22a20
Ilya
сейчас попробую натянуть
Denis
Ilya
немного неправильно, в этом случае придется везде заворачивать по месту использования
Ilya
я вообще пытаюсь сделать что бы у меня была монада пораждающая значения типа T
Ilya
и возможны всякие другие типы, которые тоже можно привести к типу Gen T
Ilya
например локальная или глобальная переменная
Ilya
собственно для этого и есть тайплкасс продьюсер
Ilya
а заассайненый тайп OutType это типа оутпут продьюсера, но проблема что я не могу его задефайнить для непосредственно абстрактной монады с констрейнтом GenFunMonad, потому что тайпчекер отбрасывает этот контекст и спроведливо жалуется что инстанс для монадического кейса свлишком общий
Denis
Ilya
пользователи библиотеки будут страдать
Ilya
дырявая абстракция получается
Ilya
у меня так-то есть реализация без GenFunMonad где конкретная монада лежит и там всё это прекрасно работает
Ilya
но проблема в том, что в этом случае не получится нормально заворачивать конкретную монаду в другие трансформеры
Ilya
попробовал извратиться через фандепы, но уткнулся в то же самое место
Denis
так, дальше код надо смотреть
Denis
я пальцем в небо попытался понять что хотите
Ilya
сценарий использования приблизительно такой
Ilya
https://github.com/SPY/haskell-wasm/blob/master/src/Language/Wasm/Builder.hs#L807-L825
кана
круто бы примеры упрощать до абстрактных, а то тут сходу кучу ненужной информации, вместо понимания проблемы я читаю именя типов чтобы понять что это
Ilya
да, я пытался вначале 🙂
Ilya
попробую абстракнее сформулировать
кана
ну как я понял
Denis
где-то было у меня такое недавно
кана
нужен инстанс семейств от констрейтов инстансов
Ilya
Denis
@lonokhov У тебя вроде вот с сервантом такая же шляпа была как человек спрашивает. Не могу вспомнить точное решение, но смутно помню, что там нужно чтобы правая часть была разная в разных ассоциированных TF. Не напомнишь?
Denis
https://gist.github.com/SPY/ff745898629800f967949cd14ead1ed5
Denis
Ilya у @lonokhov было такое недавно, можно как-то переписать чтобы все работало
Dmitry
А мое предложение не устраивает?
Denis
если мне память не изменяет, то правые части в TF разные должны быть
Denis
сходу я бы предложить попробовать с Tagged вместо Proxy, чтобы их дифференцировать, но возможно я фигню говорю
Denis
Leonid 🦇
Тут в обоих случаях Proxy t выходит. У меня выходило разное
Dmitry
"правые части в TF разные" - я не понимаю, что ты имеешь в виду. Можно пример, чего нельзя?
Denis
впрочем, если работает уже, то почему бы и нет?
Dmitry
насчет "работает" - не факт ;-)
кана
про правые части - это уже какая-то инъективность
Ilya
дочь периодически заставлять отвлекаться от хаскеля 🙂
кана
фандепы в данной ситуации будут иметь те же проблемы, что и семейства
Ilya
Denis
кана
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
data Wrapper a = Wrapper
class Class a where
type ClassType a
instance Class (Wrapper t) where
type ClassType (Wrapper t) = t
instance Monad m => Class (m (Wrapper t)) where
type ClassType (m (Wrapper t)) = t
вот уменьшенный пример
Зигохистоморфный
это же Proxy
data Wrapper a = Wrapper
кана
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
data Wrapper a = Wrapper
class Class a b | a -> b
instance Class (Wrapper t) t
instance Monad m => Class (m (Wrapper t)) t
и вот он на фандепах
кана
кана
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
data Wrapper1 a = Wrapper1
data Wrapper2 a = Wrapper2
class Class a b | a -> b
instance Class (Wrapper1 t) t
instance Monad m => Class (m (Wrapper2 t)) t
взял разные обертки чтобы ближе к оригиналу
Ilya
что бы совсем ближе надо из враппера1 доставать враппер2
Ilya
и из m (Wrapper1 t) тоже доставать Wrapper2 t
Ilya
в этом случае как раз GHC резонно начинается ругаться что инстанс для монады полностью оверлапит инстанс для узкого кейса
Ilya
потому что у Wrapper1 и (Monad m => m) одинаковые кайнды, как и у внутренних t и (Proxy t)
Denis
чего-то я выше недопонял задачу и нагнал люто
Denis
дополнительный параметр как Дмитрий предложил должен помочь
Ilya
похоже что работает, сейчас попробую расскоментировать и подправить основной кодбейз и посмотрим не вылезут ли какие-то краевые кейсы при интеграции с другими хаками
Ilya
вот компилирующийся сжатый экзампл
https://gist.github.com/SPY/dc5e70d1bb4de813446c1dd3391b61ae#file-overlapedmulti-hs
Ilya
вроде разобрался почему он работает(сначала не очевидно было)
Dmitry
TF IsLoc можно не делать на последних GHC. Использовать (==)
import Data.Type.Equality
...... ProducerB (Loc == m) m (m a))
Ilya
последние это от 8.4?