
Today, I was plugging away on a program and I ran into a problem. It seems that ErrorT can or can not take a type synonym as its monad, depending on how the type synonym was defined. For example, consider this GHCi interactive run:
:k Maybe Maybe :: * -> * let { a :: ErrorT String Maybe Bool; a = undefined } :t a a :: ErrorT String Maybe Bool
:k State (Scope VVar) State (Scope VVar) :: * -> * let { a :: ErrorT String (State (Scope VVar)) Bool; a = undefined } :t a a :: ErrorT String (State (Scope VVar)) Bool
ScopeState is defined in a file as:
type ScopeState a = State (Scope VVar) a
:k ScopeState ScopeState :: * -> * let { a :: ErrorT String ScopeState Bool; a = undefined }
<interactive>:1:6: Type synonym `ScopeState' should have 1 argument, but has been given 0 In the type signature: a :: ErrorT String ScopeState Bool Now, I was going to ask something like, "How can I define my type synonym so I can do this," but I figured out while writing this email that if I define ScopeState a different way:
type ScopeState = State (Scope VVar)
:k ScopeState ScopeState :: * -> * let { a :: ErrorT String ScopeState Bool; a = undefined } :t a a :: ErrorT String ScopeState Bool
So, my new question is: Why does it matter how ScopeState is defined? Bryan Burgers

Type synonyms are like type level functions. So long as they are fully applied, the type checker can treat them like macros, and expand them at compile time. But if they are only partially applied, it can't. Allowing full functions at the type level makes type inference practically impossible, so it's banned. In your case, the definition type T = S Int and type T a = S Int a might reasonably be considered equivalent, since eta reduction can turn the latter into the former. GHC could do automatic eta reduction, but people don't write such type synonyms very much (I think), so it doesn't. Simon | -----Original Message----- | From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of | Bryan Burgers | Sent: 02 February 2007 22:18 | To: haskell-cafe@haskell.org | Subject: [Haskell-cafe] It matters how Type Synonyms are defined? | | Today, I was plugging away on a program and I ran into a problem. It | seems that ErrorT can or can not take a type synonym as its monad, | depending on how the type synonym was defined. For example, consider | this GHCi interactive run: | | > :k Maybe | Maybe :: * -> * | > let { a :: ErrorT String Maybe Bool; a = undefined } | > :t a | a :: ErrorT String Maybe Bool | | > :k State (Scope VVar) | State (Scope VVar) :: * -> * | > let { a :: ErrorT String (State (Scope VVar)) Bool; a = undefined } | > :t a | a :: ErrorT String (State (Scope VVar)) Bool | | ScopeState is defined in a file as: | > type ScopeState a = State (Scope VVar) a | | > :k ScopeState | ScopeState :: * -> * | > let { a :: ErrorT String ScopeState Bool; a = undefined } | | <interactive>:1:6: | Type synonym `ScopeState' should have 1 argument, but has been given 0 | In the type signature: a :: ErrorT String ScopeState Bool | | Now, I was going to ask something like, "How can I define my type | synonym so I can do this," but I figured out while writing this email | that if I define ScopeState a different way: | > type ScopeState = State (Scope VVar) | | > :k ScopeState | ScopeState :: * -> * | > let { a :: ErrorT String ScopeState Bool; a = undefined } | > :t a | a :: ErrorT String ScopeState Bool | | So, my new question is: Why does it matter how ScopeState is defined? | | Bryan Burgers | _______________________________________________ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe

On Fri, Feb 02, 2007 at 04:18:19PM -0600, Bryan Burgers wrote:
Now, I was going to ask something like, "How can I define my type synonym so I can do this," but I figured out while writing this email that if I define ScopeState a different way:
type ScopeState = State (Scope VVar)
this is off-topic, but this is a perfect example of where newtype deriving is great.
newtype ScopeState a = ScopeState (State (Scope VVar) a) deriving(Monad,Functor,State (Scope VVar))
I just really like this idiom is all. Using it pervasively pays off greatly. John -- John Meacham - ⑆repetae.net⑆john⑈

Agreed. I've written quite a bit of code that way myself. Looking at
Iavor's monadLib, though, raised a question: has there been any
consider of removing the requirement that the newtype be the last
argument? The classes for state monads, etc. are rather backwards as
it is, since the independent type (and the primary point of the class)
is always written last. It seems like it should be equally easy to
support something like:
newtype Scopestate a = ScopeState (State (Scope VVar) a)
deriving (Monad ScopeState, Functor ScopeState, StateM ScopeState
(Scope VVar))
or even, ideally, a mixture of the two.
/g
On 2/2/07, John Meacham
On Fri, Feb 02, 2007 at 04:18:19PM -0600, Bryan Burgers wrote:
Now, I was going to ask something like, "How can I define my type synonym so I can do this," but I figured out while writing this email that if I define ScopeState a different way:
type ScopeState = State (Scope VVar)
this is off-topic, but this is a perfect example of where newtype deriving is great.
newtype ScopeState a = ScopeState (State (Scope VVar) a) deriving(Monad,Functor,State (Scope VVar))
I just really like this idiom is all. Using it pervasively pays off greatly.
John
-- John Meacham - ⑆repetae.net⑆john⑈ _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- It is myself I have never met, whose face is pasted on the underside of my mind.
participants (4)
-
Bryan Burgers
-
J. Garrett Morris
-
John Meacham
-
Simon Peyton-Jones