For example, ParsecT has multiple type variables in its definition.
newtype ParsecT s u m a
    = ParsecT {unParser :: forall b .
                 State s u
              -> (a -> State s u -> ParseError -> m b) 
              -> (ParseError -> m b)                   
              -> (a -> State s u -> ParseError -> m b) 
              -> (ParseError -> m b)                   
              -> m b
             } 
Can we do it like this ?
newtype ParsecT m a s u     -- Only the order of s u m a is changed to m a s u.
    = ParsecT {unParser :: forall b .
                 State s u
              -> (a -> State s u -> ParseError -> m b) 
              -> (ParseError -> m b)                   
              -> (a -> State s u -> ParseError -> m b) 
              -> (ParseError -> m b)                   
              -> m b
             }
I am wondering whether there is a rule or principle about the order of type variables when we define a newtype.
In Haskell, each type variable is generally a lower-case letter. threshold :: Double -> ( Double -> a ) -> ( Double -> a ) In this case, we're saying to let a be the type of the first parameter function's parameter; the returned function's parameter must also be of that type.
Within a given scope, a variable in Haskell gets defined only once and cannot change. The variables in Haskell seem almost invariable, but they work like variables in mathematics. In a math classroom, you never see a variable change its value within a single problem.
If you need to figure out what the type of an object is in a Haskell program, I hope this is helpful. Note that if you are in GHCI, you can just put :type before your expression to determine the expression's type, or use :set +t to see the type of every expression in GHCI.
in goes along with let to name one or more local expressions in a pure function.
In this case, a is last because we want ParsecT s u m __ to be a monad, that way, what our parsers look for can depend on what they found before, and so forth.  If u came last we couldn't write 
 instance Monad m => Monad (ParsecT s u m) where ...
m is next-to-last because we want ParsecT s u to be a 'monad transformer' 
 class MonadTrans t where 
     lift :: m a -> t m a 
 instance MonadTrans (ParsecT s u) where ...
If we put the m first, this instance wouldn't be possible.  There doesn't seem to be any similar reason for the ordering of s and u.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With