[Haskell-beginners] forall confusion

Brandon S. Allbery KF8NH allbery at ece.cmu.edu
Sat May 29 14:43:39 EDT 2010

On May 29, 2010, at 11:35 , Philip Scott wrote:
> Hi all,
> I was wondering if someone could give me an intuitive explanation of  
> why in
> f :: forall a.(Show a) => a -> String
> f x = show x
> "forall a.(Show a) => a" appears to translate into "Any a, as long  
> as it is an instance of Show"
> but if I use forall in an type qualifier in an assignment:
> myList = [] :: [forall a.(Show a) => a]
> "forall a.(Show a) => a" seems to mean "Any a, as long as it is  
> bottom"

Using the WikiBook's DataBox type as an example:

In the case of [DataBox], I can build list elements with SB (a valid  
value for a [Databox] is [SB 1]); what name do I use in place of SB  
for the anonymous forall-ed type in myList?  Since I don't have such a  
name, the only possible value I can use is the one value that exists  
in every type:  bottom.

Other examples:

     f :: forall a. (Show a) => a -> String -- your example above


     undefined :: forall a. a -- from the Haskell Prelude

This highlights a corner case:  "f" gives you a "nickname" to use,  
namely the fact that the forall-ed type is an argument.  "undefined"  
doesn't give you any handle at all, so its only possible value is  

     data ST s a
     runST :: (forall s. ST s a) -> a

runST gives you a temporary name for "a", in the form of the returned  
value.  You don't have a name for the "s", though, as it's hidden  
inside the ST type, which doesn't have any constructors.  This is used  
to hide information:  the invocation "runST myFunc initialValue"  
invokes myFunc, passing it initialValue and a special container whose  
contents are private (the "s").  myFunc can put things into and take  
things out of the container, using the functions in Control.Monad.ST,  
and having taken a value out it can pass that value to something else  
--- but nothing outside of the definition of myFunc can get at the  
container.  This is mainly useful when you need to hide an impure  
manipulation of values:  you can do destructive updates of things  
inside the container, as long as any given input to myFunc always  
produces the same output (referential transparency:  it should always  
be possible to replace a function call with its result, meaning it  
can't depend on external state other than its parameters).  A fast  
array library can use runST to perform a destructive-update algorithm  
when it's faster than the equivalent pure algorithm, provided both  
algorithms always produce the same results for the same inputs.

brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery at kf8nh.com
system administrator [openafs,heimdal,too many hats] allbery at ece.cmu.edu
electrical and computer engineering, carnegie mellon university    KF8NH

-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 195 bytes
Desc: This is a digitally signed message part
Url : http://www.haskell.org/pipermail/beginners/attachments/20100529/3d87e212/PGP.bin

More information about the Beginners mailing list