к
Size: a a a
IO
Hold r => r
, где class c => Hold c
instance c => Hold c
, r
вместо очевидного \dict -> dict
дает \_ -> knownDict
. eitherC
дает в качестве Hold r
undefined
и с помощью unsafePerformIO
смотрит, вылетел ли экcепшн. Если нет - у нас на руках r
, если вылетел - фоллбэкаемя на l
. Hold r => r
как тривиальный, Hold
определен в .hs-boot
без суперкласса и импортирован {-# SOURCE #-}
, так что он еще не тривиальный.[
IO
eitherC
в майне не определить.SOURCE
импортирован Hold
, иначе ghc сразу выкидывает Hold r => r
как тривиальный и сказке конец.SOURCE
импорта Hold
either-констрейнты вообще не разрешаются, после все немедленно разрешаются, выбирая дефолтный констрейнт если второй еще не появился.ЖК
type Bar a b = b
Bar Bool Int
и получить Int
.IO
FooType a q = q
и уберем FooType
вообще:class Foo a whereЭто дает ту же самую ошибку, expected
foo :: a -> q
instance Num n => Foo [x] where
foo :: forall q . [x] -> q
foo xs = fromIntegral $ length xs :: n
q
got n
, что вроде логично: n
вообще не при делах, она введена в инстанс хеаде и с q
никак не связанна. Вообще идея трогать в констрейнтах типопеременные которых нет в самом классе идея такая себе, о чем компилятор подсказывает требуя включить AllowAmbiguousTypes
.Num n =>
в инстансе добавить Num q =>
в класс все заработает:class Foo a where
type FooType a q
foo :: Num q => a -> FooType a q
instance Foo [x] where
type FooType [x] g = g
foo xs = fromIntegral $ length xs
MP
finallyError :: MonadError e m => m a -> m () -> m a
finallyError tryF finallyF =
tryIt `catchError` catchIt
where
tryIt = do
z <- tryF
finallyF
pure z
catchIt e = finallyF >> throwError e
MP
finallyF
может быть разным, и имплементацию в общем случае нельзя сделатьMP
MP
MP