к
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 = bBar 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