EDIT: This answer tackles issues directly pointed in the question like:
guard
usage, MonadPlus
context and newtype
deriving.
I think that @Fyodor Soikin answer tackles the essence of this problem by replacing guard
with when
so this answer can be treated as supplementary material.
I think that if you try something like:
visitNode :: Castle -> StateT (Set Castle) Maybe Unit
visitNode c = do
s <- get
guard $ not (member c s)
modify \acc -> insert c s
it should work because Maybe
has MonadZero
instance and StateT
instance depends on this.
Now let's go back and try to resolve some of the problems which you have encountered.
It gives me the error:
No type class instance was found for
Control.MonadZero.MonadZero Identity
This message tells us that Identity
has no MonadZero
instance. If we check what is a MonadZero
we are going to discover that it is a class which implicates that given type has also Monad
and Alternative
instance and which satisfies the Annihilation
law... Identity
has no Alternative
instance because it require that given type has a Plus
instance:
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
I think that it is impossible to find any good candidate for an empty
(where empty :: ∀ a. f a
) value when we have only one constructor Identity ∷ ∀ a. a → Identity a
.
For example in case of Maybe
we have empty = Nothing
and <|>
with this value always gives Nothing
.
Which I don't understand why MonadZero would not work in this context, but regardless, I attempted to derive the Identity for MonadZero with things like this:
newtype Identity a = Identity a
derive instance newtypeIdentity :: Newtype (Identity a) _
derive newtype instance monadZeroIdentity :: MonadZero Identity
When you are using newtype deriving you are telling the compiler that instance for your newtype
should use "inner type" instance as an implementation. In this case you have only a
type parameter and there is no "underlyning" instance at hand.
I think that if you want to use such a deriving you have to use concrete type which instances you want to use. For example here we are deriving Functor
for our type MaybeWrapper
which uses Maybe
instance to provide appropriate members implementation (map
in this case):
newtype MaybeWrapper a = MaybeWrapper (Maybe a)
derive instance newtypeMaybeWrapper :: Newtype (MaybeWrapper a) _
derive newtype instance functorMaybeWrapper :: Functor MaybeWrapper
Happy PureScript Hacking!