Size: a a a

2021 June 08

к

кана in Haskell
такое у тайпфемелей есть
источник

к

кана in Haskell
но не всегда, если в репле запросить тип x, то ghci зависнет

а вот если использовать x, то будет ошибка про 201 редукцию
источник

AS

Anton Sorokin in Haskell
Надо бы про UndecidableInstances как нибудь гайды написать нормальные про всё вот это
источник

AS

Anton Sorokin in Haskell
Главное, что добавление прагмы не ломает подобный (работающий без неё) код, в общем. На производительности кстати интересно как сказывается
источник

R

Roman in Haskell
охренеть
источник

IO

I O in Haskell
Если верить нотам гхц (и если я их правильно понимаю) это все-таки так сделано чтобы избежать боттомов в суперклассах.

Note [Recursive superclasses]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See #3731, #4809, #5751, #5913, #6117, #6161, which all
describe somewhat more complicated situations, but ones
encountered in practice.

See also tests tcrun020, tcrun021, tcrun033, and #11427.

----- THE PROBLEM --------
The problem is that it is all too easy to create a class whose
superclass is bottom when it should not be.

Consider the following (extreme) situation:
       class C a => D a where ...
       instance D [a] => D [a] where ...   (dfunD)
       instance C [a] => C [a] where ...   (dfunC)
Although this looks wrong (assume D [a] to prove D [a]), it is only a
more extreme case of what happens with recursive dictionaries, and it
can, just about, make sense because the methods do some work before
recursing.

To implement the dfunD we must generate code for the superclass C [a],
which we had better not get by superclass selection from the supplied
argument:
      dfunD :: forall a. D [a] -> D [a]
      dfunD = \d::D [a] -> MkD (scsel d) ..

Otherwise if we later encounter a situation where
we have a [Wanted] dw::D [a] we might solve it thus:
    dw := dfunD dw
Which is all fine except that now ** the superclass C is bottom **!

The instance we want is:
      dfunD :: forall a. D [a] -> D [a]
      dfunD = \d::D [a] -> MkD (dfunC (scsel d)) ...

----- THE SOLUTION --------
The basic solution is simple: be very careful about using superclass
selection to generate a superclass witness in a dictionary function
definition.  More precisely:

 Superclass Invariant: in every class dictionary,
                       every superclass dictionary field
                       is non-bottom

To achieve the Superclass Invariant, in a dfun definition we can
generate a guaranteed-non-bottom superclass witness from:
 (sc1) one of the dictionary arguments itself (all non-bottom)
 (sc2) an immediate superclass of a smaller dictionary
 (sc3) a call of a dfun (always returns a dictionary constructor)

The tricky case is (sc2).  We proceed by induction on the size of
the (type of) the dictionary, defined by GHC.Tc.Validity.sizeTypes.
Let's suppose we are building a dictionary of size 3, and
suppose the Superclass Invariant holds of smaller dictionaries.
Then if we have a smaller dictionary, its immediate superclasses
will be non-bottom by induction.

What does "we have a smaller dictionary" mean?  It might be
one of the arguments of the instance, or one of its superclasses.
Here is an example, taken from CmmExpr:
      class Ord r => UserOfRegs r a where ...
(i1)   instance UserOfRegs r a => UserOfRegs r (Maybe a) where
(i2)   instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where

For (i1) we can get the (Ord r) superclass by selection from (UserOfRegs r a),
since it is smaller than the thing we are building (UserOfRegs r (Maybe a).

But for (i2) that isn't the case, so we must add an explicit, and
perhaps surprising, (Ord r) argument to the instance declaration.

TLDR:

Вполне легально иметь осмысленный

class A a
class A a => B a
instance A a => A a
instance B a => B a

Но в инстансе B гхц может захотеть достать из переданного B суперкласс A и получит боттом, вместо того чтобы взять fix instanceA и получить что-то осмысленное.

В качестве фикса суперклассы можно доставать только из меньших по типу словарей, так что в instance X a => Y a использовать суперкласс X чтобы создать суперкласс Y нельзя.
источник

IO

I O in Haskell
И в принципе достать из undecidable инстанса суперкласс можно, вот это компилируется

class Eq x => A x
instance Eq x => A x

class B x where b :: Dict (Eq x)
instance A x => B x where b = Dict


Нельзя именно решать суперклассом не меньшего given-а требуемый суперкласс
источник

m

monagatep in Haskell
Подскажите, пожалуйста, какие-нибудь туториалы по сборке своих монадных стеков.

Вот есть приложенние, хочу в нём более чётко разделить доступы. У меня сейчас какой-то самопальный огород из

saveToDb :: (HasLog m, HasDb m) => SomeData -> m (Either Text Result)

Хотелось бы посмотреть, как грамотные люди это делают.

Есть какие-нибудь хорошие примеры? Может, есть открытые готовые приложения, где подобные идеи эксплуатируются?
источник

OS

Oleksandr Shyshko in Haskell
очень похоже на polysemy (таймкод)
https://youtu.be/idU7GdlfP9Q?t=1395
источник

MK

Maxim Koltsov in Haskell
Есть миллион способов
Mtl-like, handle pattern, free monads, системы эффектов
источник

MK

Maxim Koltsov in Haskell
Можно гуглить эти слова и выбирать что нравится
источник

AP

Aleksei (astynax) Pi... in Haskell
HasLog, HasDb — это скорее всего вариации на тему Reader с HList внутри
источник

MK

Maxim Koltsov in Haskell
Можно и без H
источник

AP

Aleksei (astynax) Pi... in Haskell
Можно
источник

AP

Aleksei (astynax) Pi... in Haskell
А вообще тут кейворды "composable effects" (вводить на хакедже)
источник

AP

Aleksei (astynax) Pi... in Haskell
источник

AP

Aleksei (astynax) Pi... in Haskell
Да хоть вот это вот
источник

MK

Maxim Koltsov in Haskell
Я бы советовал сначала немного почитать об этом всём, чем просто тащить какую-либо либу
источник

AP

Aleksei (astynax) Pi... in Haskell
Это правда
источник

AP

Aleksei (astynax) Pi... in Haskell
mtl — must have так или иначе
источник