РЕДАКТИРОВАТЬ: Этот ответ решает вопросы, прямо указанные в вопросе, как:
guard
использование, MonadPlus
контекст и newtype
получение.
Я думаю, что ответ @Fyodor Soikin решает суть этой проблемы, заменяя guard
на when
, поэтому этот ответ можно рассматривать как дополнительный материал.
Я думаю, что если вы попробуете что-то вроде:
visitNode :: Castle -> StateT (Set Castle) Maybe Unit
visitNode c = do
s <- get
guard $ not (member c s)
modify \acc -> insert c s
это должно работать, потому что Maybe
имеет экземпляр MonadZero
, а экземпляр StateT
зависит от этого.
Теперь давайте вернемся и попробуем решить некоторые проблемы, с которыми вы столкнулись.
выдает ошибку:
No type class instance was found for
Control.MonadZero.MonadZero Identity
Это сообщение говорит нам, что у Identity
нет экземпляра MonadZero
. Если мы проверим, что такое MonadZero
, мы обнаружим, что это класс, который подразумевает, что данный тип имеет также экземпляр Monad
и Alternative
и который удовлетворяет закону Annihilation
. . Identity
не имеет экземпляра Alternative
, так как требует, чтобы данный тип имел Plus
экземпляр:
The Plus type class extends the Alt type class with a value that should be the left and right identity for (<|>)
(...)
Members:
empty :: forall a. f a
Я думаю, что невозможно найти какого-либо хорошего кандидата для значения empty
(где empty :: ∀ a. f a
), когда у нас есть только один конструктор Identity ∷ ∀ a. a → Identity a
.
Например, в случае Maybe
у нас есть empty = Nothing
и <|>
с этим значением всегда дает Nothing
.
Что я не понимаю, почему MonadZero не будет работать в этом контексте, но независимо от этого, я попытался получить Identity для MonadZero с помощью таких вещей:
newtype Identity a = Identity a
derive instance newtypeIdentity :: Newtype (Identity a) _
derive newtype instance monadZeroIdentity :: MonadZero Identity
Когда вы используете наследование newtype, вы говорите компилятору, что экземпляр для вашего newtype
должен использовать экземпляр "внутреннего типа" в качестве реализации. В этом случае у вас есть только параметр типа a
, и «лежащего в основе» экземпляра нет.
Я думаю, что если вы хотите использовать такое производное, вы должны использовать конкретный тип, какие экземпляры вы хотите использовать. Например, здесь мы извлекаем Functor
для нашего типа MaybeWrapper
, который использует экземпляр Maybe
для обеспечения соответствующей реализации членов (в данном случае map
):
newtype MaybeWrapper a = MaybeWrapper (Maybe a)
derive instance newtypeMaybeWrapper :: Newtype (MaybeWrapper a) _
derive newtype instance functorMaybeWrapper :: Functor MaybeWrapper
Счастливого взлома PureScript!