параметров, поэтому экзистеншиал)
data Alg p where
Alg :: forall m p . (Monad m, Eq p) => {
select :: m Direction,
step :: Direction -> p -> m p,
stopCond :: p -> m Bool
} -> Alg p
Как теперь написать алгоритм, использующий эти "методы"? Наивная попытка
algorithm :: forall m p . (Monad m, Show p) => Alg p -> p -> m [p]
algorithm Alg{..} start = go start []
where
go :: p -> [p] -> m [p]
go p1 xs = do
stop <- stopCond p1
if stop then return xs
else do
dir <- select
p2 <- step dir p1
go p2 (p2:xs)
вызывает ошибку
Error:(73, 15) warning: [-Wdeferred-type-errors]
• Couldn't match type ‘m1’ with ‘m’
‘m1’ is a rigid type variable bound by
a pattern with constructor:
Alg :: forall (m :: * -> *) p.
(Monad m, Eq p) =>
m Direction -> (Direction -> p -> m p) -> (p -> m Bool) -> Alg p,
in an equation for ‘algorithm’
‘m’ is a rigid type variable bound by
the type signature for:
algorithm :: forall (m :: * -> *) p.
(Monad m, Show p) =>
Alg p -> p -> m [p]
То есть с одной стороны экзистеншиал диктует свой m, с другой стороны сигнатура алгоритма диктует свой m, как бы подсказать компилятору, что они всегда равны?
Почему необходимо было убрать параметр из Alg? Потому что монада может описываться типом, который зависит от этого параметра и тогда получим бесконечный тип, чего конечно хочется избежать.
Какие у меня варианты?
UPD. Похоже нужно всё-таки как-то выживать с Alg m p
Они как раз по типу не всегда равны
Обсуждают сегодня