<div dir="ltr"><div>When you are defining a class, the actual type that the class will accept can be further restricted. For example</div><div><br></div><div>:i Num<br></div><div>class Num a where</div><div><br></div><div>is shorthand for</div><div><br></div><div>class Num (a :: *) where</div><div><br></div><div>When you see the *, you should say in your head the word "type". Off topic, but In fact in future ghc releases, you will stop using * and use the Type type in its place, because it is clearer. So any Num instances require a single Type to be complete.<br></div><div><br></div><div>That means that only types that can be an instance of Num must have a kind *. Things that have that type are plain types that don't have extra variables, such as Int, (), and Char. If you tried to make Maybe an instance of Num it just wouldn't work.<br></div><div><br></div><div>Monad takes a different type</div><div>:i Monad</div><div>class Applicative m => Monad (m :: * -> *) where</div><div><br></div><div>It says that the only Monad instances take a Type and return a Type. For example Maybe takes a * and returns a *. That means you can apply Int, (), and Char to Maybe and you will get back a complete Type (ie. Maybe Int). So while Maybe can't be a num, Maybe Int absolutely can be an instance of Num. Other types that can be Monads - IO, [] (list) for example.<br></div><div><br></div><div>MonadTrans is even more involed</div><div><br></div><div>class MonadTrans (t :: (* -> *) -> * -> *) where</div><div><br></div><div>So, in this case it takes a type that is like Maybe or IO, and then also takes another that is like Int or Char. The standard example is StateT.</div><div><br></div><div>newtype StateT s (m :: * -> *) a</div><div>instance [safe] MonadTrans (StateT s)</div><div><br></div><div>So you can see how the types fit together. MonadTrans requires a type that has the right shape, and StateT s without the extra paramters fits perfectly.<br></div><div><br></div><div>So when you have a</div><div><br></div><div><span class="gmail-pl-k">newtype</span> <span class="gmail-pl-en">Scope</span> <span class="gmail-pl-smi">b</span> <span class="gmail-pl-smi">f</span> <span class="gmail-pl-smi">a</span> <span class="gmail-pl-k">=</span> <span class="gmail-pl-ent">Scope</span> <span class="gmail-pl-k">{</span> <span class="gmail-pl-e">unscope</span> <span class="gmail-pl-k">::</span> <span class="gmail-pl-smi">f</span> (<span class="gmail-pl-en">Var</span> <span class="gmail-pl-smi">b</span> (<span class="gmail-pl-smi">f</span> <span class="gmail-pl-smi">a</span>)) <span class="gmail-pl-k">}</span></div><div><span class="gmail-pl-k"><br></span></div><div><span class="gmail-pl-k">You can see that if a is a monomorphic type like Char or Int, then f has to be something like Maybe [], or IO, or Maybe. So you can see how Scope fits into both Monad and MonadTrans.</span></div><div><span class="gmail-pl-k"><br></span></div><div><span class="gmail-pl-k"></span><span class="gmail-pl-k">instance</span> <span class="gmail-pl-en"><span class="gmail-pl-e">Monad</span></span> <span class="gmail-pl-smi">f</span> <span class="gmail-pl-k">=></span> <span class="gmail-pl-en"><span class="gmail-pl-e">Monad</span></span> (<span class="gmail-pl-en">Scope</span> <span class="gmail-pl-smi">b</span> <span class="gmail-pl-smi">f</span>) <span class="gmail-pl-k">where</span></div><div><span class="gmail-pl-k">instance</span> <span class="gmail-pl-en">MonadTrans</span> (<span class="gmail-pl-en">Scope</span> <span class="gmail-pl-smi">b</span>) <span class="gmail-pl-k">where</span></div><div><span class="gmail-pl-k"><br></span></div><div><span class="gmail-pl-k">Hopefully this gives you some intuition on how it works?<br></span></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Aug 19, 2018 at 4:31 PM, Anthony Lee <span dir="ltr"><<a href="mailto:anthonynlee@gmail.com" target="_blank">anthonynlee@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hi,</div><div>In Scope.hs there is one instance of Monad and one instance of MonadTrans for Scope,</div><div>For the Monad instance, it is defined like this: Monad (Scope b f);</div><div>For the MonadTrans instance, it is like this: MonadTrans (Scope b);</div><div>Does it mean:</div><div> In ">>=" the e represents (a) of (Scope b f a)?</div><div> In lift function the m represents (f a) of (Scope b f a)?</div><div><br></div><div><a href="https://github.com/ekmett/bound/blob/master/src/Bound/Scope.hs" target="_blank">https://github.com/ekmett/<wbr>bound/blob/master/src/Bound/<wbr>Scope.hs</a><br></div><div>========================Scope.<wbr>hs============================<wbr>====<br></div><div>instance Monad f => Monad (Scope b f) where</div>#if !MIN_VERSION_base(4,8,0)<br> return a = Scope (return (F (return a)))<br> {-# INLINE return #-}<br>#endif<br> Scope e >>= f = Scope $ e >>= \v -> case v of<br> B b -> return (B b)<br> F ea -> ea >>= unscope . f<br> {-# INLINE (>>=) #-}<br><br>instance MonadTrans (Scope b) where<br> lift m = Scope (return (F m))<br> {-# INLINE lift #-}<br></div>
<br>______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
<br></blockquote></div><br></div>