https://wiki.haskell.org/api.php?action=feedcontributions&user=Jsnx&feedformat=atomHaskellWiki - User contributions [en]2020-03-29T01:20:53ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Applications_and_libraries/Web_programming&diff=32684Applications and libraries/Web programming2009-12-20T21:06:05Z<p>Jsnx: Dead links.</p>
<hr />
<div>[[Category:Web|*]]<br />
Web, HTTP, HTML and XML programming.<br />
<br />
== Applications ==<br />
<br />
See also the [[Libraries_and_tools/Network|network category]].<br />
<br />
=== Haskell web applications ===<br />
<br />
;[http://hpaste.org/ hpaste: the haskell pastebin]<br />
:A pastebin site for Haskell runnning on top of [[HAppS]]. [http://www.scannedinavian.com/~eric/hpaste Source].<br />
<br />
;[http://pass.net/ pass.net]<br />
:Replaces registration, confirmation mails, and multiple passwords with a single login. at your email domain. Runs on HAppS.<br />
<br />
;[http://www.parallelnetz.de/ Parallel web]<br />
:Suggests that you travel through a parallel web with translated content. It's based on Simon Marlow's Haskell Web Server.<br />
:For Haskellers: Test the Monad Transformer in [http://www.haskell.org.MonadTransformer.parallelnetz.de/haskellwiki/Category:Monad a parallel Haskell wiki].<br />
:For Germans: Search in [http://www.google.de.saxophone.parallelnetz.de/ Saxon dialect] or check out the [http://www.stoiber.de.Ehmulator.parallelnetz.de/ Ehmulator].<br />
:Hosted on [http://sourceforge.net/projects/parallelweb SourceForge].<br />
<br />
=== Web servers ===<br />
<br />
;[http://darcs.haskell.org/hws/ Haskell Web Server (hws)]<br />
:Simon Marlow's concurrent Haskell web server<br />
<br />
;[http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mohws Modular Haskell Web Server (mohws)]<br />
:A web server with a module system and support for CGI. Based on Simon Marlow's original Haskell Web Server.<br />
<br />
;[http://www.informatik.uni-freiburg.de/~thiemann/WASH/#wsp Wash Server Pages]<br />
:An extended version of Simon Marlow's webserver (hws) that runs WASH modules as servlets.<br />
<br />
=== Site verification ===<br />
<br />
;[http://www.dsic.upv.es/users/elp/GVerdi GVerdi]<br />
:A Rule-based System for Web site Verification<br />
<br />
=== Wikis ===<br />
<br />
;[http://www.flippac.org/projects/flippi/ Flippi]<br />
:A wiki written in Haskell<br />
<br />
;[http://pandocwiki.googlecode.com/ PandocWiki]<br />
:A simple wiki using HAppS and Pandoc<br />
<br />
;[http://latexki.nomeata.de/ latexki]<br />
:Subversion based Wiki for collaborative editing of LaTeX documents,<br />
<br />
;[http://hikij.wellquite.org/ Hikij]<br />
:A wiki written in Haskell and Javascript<br />
<br />
=== Content-management systems ===<br />
<br />
;[http://hope.bringert.net/ Hope]<br />
: An extensible Haskell content management system<br />
<br />
;[http://www.acooke.org/jara/halipeto/index.html Halipeto]<br />
:Halipeto by Andrew Cooke is a simple system for generating web pages from templates and a database. It currently only includes support for a simple database based on text files. ''Full documentation but unmaintained.''<br />
<br />
=== XML ===<br />
<br />
;[http://www.cs.york.ac.uk/fp/Xtract/ Xtract]<br />
:Xtract is a `grep'-like command-line tool for searching XML and HTML documents. Note that Xtract is now part of HaXml, listed below in Libraries.<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/haskell/lambdaFeed/ lambdaFeed]<br />
:Manuel Chakravarty's RSS 2.0 feed generator. It reads news items - in a non-XML, human-friendly format - distributed over multiple channels and renders them into the RSS 2.0 XML format understood by most news aggregators as well as into HTML for inclusion into web pages.<br />
<br />
;[http://johnmacfarlane.net/pandoc/ Pandoc]<br />
:Pandoc is a Haskell library for converting from one markup format to another, and a command-line tool that uses this library. It can read markdown and (subsets of) reStructuredText, HTML, and LaTeX, and it can write markdown, reStructuredText, HTML, DocBook XML, LaTeX, ConTeXt, RTF, groff man, and S5 HTML slide shows. It also supports extensions to markdown syntax for footnotes, inline LaTeX, definition lists, strikeout, tables, and more.<br />
<br />
=== CSS ===<br />
<br />
;[http://zamez.org/factorcss Factor CSS]<br />
:This tool takes a CSS stylesheet on input and produces an almost equivalent stylesheet on output, but with rulesets split, combined, and reordered to "factor out" common declarations. This helps reveal shared components. The resulting stylesheet may also be smaller.<br />
<br />
== Libraries ==<br />
<br />
=== HTTP ===<br />
<br />
;[http://www.haskell.org/http/ HTTP and Browser Modules]<br />
:A significantly RFC compliant HTTP/1.1 client implementation. This is an updated version of [http://homepages.paradise.net.nz/warrickg/haskell/http/ Warrick Gray's original version].<br />
<br />
===AJAX===<br />
<br />
<br />
;[http://darcs.haskell.org/SoC/hsp.clientside/ HSP Clientside]<br />
:HSPClientside is a library for generating client-side scripts (in JavaScript) from [http://www.cs.chalmers.se/~d00nibro/hsp/ Haskell Server Pages] (HSP).<br />
<br />
=== Web frameworks ===<br />
<br />
;[http://www.turbinado.org/Home Turbinado]<br />
:Turbinado is a fast, easy-to-use web application framework for Haskell.<br />
<br />
;[http://happs.org/ HAppS - Haskell Application Server]<br />
:The Haskell Application Server contains a monadic framework for ACID transactions, an HTTP server (outperforms Apache/PHP in informal benchmarks), an SMTP server and mail delivery agent. A DNS resolver in pure Haskell. And XML and XSLT support. See also [[HAppS]], [[HAppS tutorial]].<br />
<br />
;[http://pass.net/s/repo Pass.Net] <br />
:Provides web sites with a simple shared web API to manage user logins, confirmation emails, forgotten passwords, etc. Most application frameworks dont have complete libraries to cover all of this functionality. Outsourcing this to Pass.net means less complexity in your application and less worrying about mail delivery, mail server integration, etc. Pass.Net is currently beta. We expect it to be fully live and reliable by the end of the year. Pass.Net is written in Haskell using HAppS and provides an easy to use Haskell library for HAppS user. Clients in python, php, and java coming soon.<br />
<br />
;[http://www.informatik.uni-freiburg.de/~thiemann/haskell/WASH/ WASH]<br />
:A family of combinator libraries for programming Web applications. WASH/HTML is for generating dynamic HTML documents, combining flexibility and safety. WASH/CGI is for server-side Web scripting with sessions, compositional forms, and graphics.<br />
<br />
;[[HSP|Haskell Server Pages]]<br />
:Using Haskell as a server-side scripting language, extended to allow embedded XML/XHTML fragments in Haskell code.<br />
<br />
;[http://darcs.haskell.org/~lemmih/hasp/ HASP]<br />
:HASP is a fork of Niklas Broberg?s Haskell Server Pages. Changes includes:<br />
* support for all GHC extensions<br />
* front-end based on FastCGI instead of its own web server<br />
* minor bug fixes and performance tuning.<br />
<br />
;[http://www.cs.uu.nl/wiki/WebFunctions/WebHome WebFunctions]<br />
:WebFunctions is a [[EDSL]] for developing websites, implemented in Haskell. WebFunctions is a domain specific embedded language for web authoring.<br />
<br />
;[http://www.cin.ufpe.br/~haskell/hwsproxygen/ HWSProxyGen]<br />
:A web services proxy generator for the Haskell functional language, implemented in Haskell and C#. The final purpose is to show that Haskell and functional languages in general can be used as a viable way to the implementation of distributed components and applications, interacting with services implemented in different languages and/or platforms.<br />
<br />
;[[Hajax]] <br />
: A proposed tool to develop Ajax applications (stand-alone Web applications that execute into the browser environment) in Haskell.<br />
<br />
;[[Haskell_in_web_browser|Haskell Web Toolkit]] <br />
:A client-side (for programs running inside inside web browser) API layer on top of DOM, part of [[Yhc/Javascript|Yhc Javascript backend]]<br />
<br />
;[http://community.haskell.org/~sclv/hvac/ hvac] <br />
:A transactional, declarative framework for lightweight web applications. Documentation is available at [http://community.haskell.org/~sclv/hvac/html_docs/hvac/]. See also the [http://fmapfixreturn.wordpress.com/2008/03/23/ann-hvac-01b-a-transactional-declarative-framework-for-lightweight-web-applications/ announcement]<br />
<br />
=== URI ===<br />
<br />
;[http://haskell.org/ghc/docs/latest/html/libraries/network/Network-URI.html Network.URI]<br />
:Included in the GHC distribution, this is very complete URI parser implementing the syntax specified by RFC3986. Based on Graham Klyne's [http://lists.w3.org/Archives/Public/uri/2003Mar/0010.html URI handling] implementation from the W3C uri mailing list, and since updated for compatibility with both GHC and Hugs. Highly recommended for parsing URLs and any other kind of URI.<br />
<br />
=== XML ===<br />
<br />
;[http://www.cs.york.ac.uk/fp/HaXml/ HaXml: utilities for using XML with Haskell]<br />
:Includes an XML parser, an HTML parser, a pretty-printer, a combinator library for generic XML transformations, and two Haskell&gt;-&lt;XML converters using type-based translation.<br />
<br />
;[http://www.fh-wedel.de/~si/HXmlToolbox/ HXT: Haskell XML Toolbox]<br />
:The Haskell XML Toolbox (HXT) bases on the ideas of HaXml and HXML, but introduces a more general approach based on arrows for processing XML with Haskell. The Haskell XML Toolbox uses a generic data model for representing XML documents, including the DTD subset and the document subset, in Haskell. It contains an XML parser, an HTML parser, namespaces are supported, XPath expressions can be used for selecting and transforming parts of a document. Validation can be performed with respect to DTDs and RelaxNG schema. A [[HXT|Getting started page]] describes the programming model behind HXT and gives some simple examples.<br />
<br />
;[http://darcs.haskell.org/wraxml WraXML]<br />
:A little wrapper to HaXML and HXT: It provides a more natural data structure for representing XML trees, and converts between HaXML or HXT and its custom tree structure. The operations on the tree need not to be of type (a -> [a]), thus using these functions is a bit more type safe. It has a custom lazy HTML parser using TagSoup and a custom lazy formatter. The library is currently much oriented to HTML rather than XML.<br />
<br />
;[http://wiki.di.uminho.pt/wiki/bin/view/PURe/2LT 2LT: Two-Level Transformation]<br />
:A two-level data transformation consists of a type-level transformation of a data format coupled with value-level transformations of data instances corresponding to that format. Examples of two-level data transformations include XML schema evolution coupled with document migration, and data mappings used for interoperability and persistence. A library of two-level transformation combinators. These combinators are used to compose transformation systems which, when applied to an input type, produce an output type, together with the conversion functions that mediate between input and out types. Front-ends for XML and SQL. These front-ends support (i) reading a schema, (ii) applying a two-level transformation system to produce a new schema, (iii) convert a document/database corresponding to the input schema to a document/database corresponding to the output schema, and vice versa. Referential constraints and primary key information are propagated through the schema transformation.<br />
<br />
;[http://www.mail-archive.com/haskell@haskell.org/msg18396.html HSXML]<br />
:A direct Haskell embedding of SXML<br />
<br />
;[http://m13s07.vlinux.de/darcs/StaticDTD/v2/ StaticDTD]<br />
:StaticDTD: complete static validness against a DTD.<br />
<br />
=== HTML ===<br />
<br />
;[http://www.cse.ogi.edu/~andy/html/intro.htm The Haskell Html Library] by Andy Gill<br />
:This library is a collection of combinators, allowing your Haskell programs to generate HTML. It is available in the standard libraries as [http://haskell.org/ghc/docs/latest/html/libraries/base/Text-Html.html Text.Html].<br />
<br />
;[http://www.haskell.org/ghc/docs/latest/html/libraries/xhtml/Text-XHtml.html XHtml library]<br />
:This is a version of [http://haskell.org/ghc/docs/latest/html/libraries/base/Text-Html.html Text.Html], modified to produce XHTML 1.0 Transitional.<br />
<br />
;[http://www.dtek.chalmers.se/~tumm/vieux/ Vieux: A Nevow implementation]<br />
:Vieux is a html-template system for Haskell. The basic idea is to define a xhtml template which is used to generate a xhtml document by Vieux.<br />
<br />
;[http://www.wellquite.org/chunks/ Text.HTML.Chunks]<br />
:Text.HTML.Chunks is a templating system inspired by the Perl HTML::Chunks module. The major change for the Haskell version is that the use of the templates is statically verified.<br />
<br />
;[http://www-users.cs.york.ac.uk/~ndm/tagsoup/ TagSoup]<br />
: TagSoup is a library for extracting information out of unstructured HTML code, sometimes known as tag-soup. The HTML does not have to be well formed, or render properly within any particular framework. This library is for situations where the author of the HTML is not cooperating with the person trying to extract the information, but is also not trying to hide the information. The library provides a basic data type for a list of unstructured tags, a parser to convert HTML into this tag type, and useful functions and combinators for finding and extracting information. <br />
<br />
=== CGI ===<br />
<br />
; [http://www.haskell.org/ghc/docs/latest/html/libraries/cgi/Network-CGI.html Network.CGI]<br />
:Simple Library for writing CGI programs. This version of the library is for systems with version 2.0 or greater of the network package. This includes GHC 6.6 and later. Features include:<br />
:* Access to CGI parameters (e.g. form input) from both GET and POST requests.<br />
:* Access to CGI environment variables.<br />
:* Ability to set arbitrary response headers.<br />
:* Support for HTTP cookies.<br />
:* Efficient file upload support.<br />
:* Wrapper [http://www.haskell.org/ghc/docs/6.6/html/libraries/cgi/Network-CGI-Compat.html functions] for compatibility with the former [http://haskell.org/ghc/docs/latest/html/libraries/network/Network-CGI.html Network.CGI] module.<br />
<br />
;[http://hackage.haskell.org/cgi-bin/hackage-scripts/package/fastcgi FastCGI library]<br />
:A library for using NewCGI programs with [http://www.fastcgi.com/ FastCGI].<br />
<br />
=== XML-RPC and CORBA ===<br />
<br />
;[http://www.haskell.org/haxr/ HaXR - the Haskell XML-RPC library]<br />
:An XML-RPC client and server library. [http://www.xmlrpc.com/ XML-RPC] is "remote procedure calling using HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned."<br />
<br />
;[http://www.dcs.shef.ac.uk/~simonf/HAIFA.html HAIFA]<br />
:HAIFA is an implementation of parts of the web-service architecture in Haskell. Notably it includes an XML serializer, a partial implementation of XML Schema and SOAP/1.1.<br />
<br />
;[http://sourceforge.net/projects/haskell-corba/ haskell-corba]<br />
:This package allows Haskell programmers to write CORBA clients and servers using the [http://www.mico.org MICO open-source CORBA implementation]. It defines a Haskell language mapping for CORBA, and includes an IDL compiler which generates Haskell stub and skeleton modules from IDL files.<br />
<br />
<br />
=== Finance ===<br />
<br />
;[http://hackage.haskell.org/cgi-bin/hackage-scripts/package/Finance-Quote-Yahoo Finance-Quote-Yahoo]<br />
:Obtain quote data from finance.yahoo.com<br />
<br />
== See also ==<br />
<br />
* A proposal for a common [[WebApplicationInterface|web application interface]] for Haskell.<br />
* [[Practical web programming in Haskell]]<br />
* Mailing list on [http://www.haskell.org/mailman/listinfo/web-devel web development]<br />
<br />
== Hackage ==<br />
<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:Web Web libraries on Hackage]<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:Network Network libraries on Hackage]<br />
<br />
{{LibrariesPage}}</div>Jsnxhttps://wiki.haskell.org/index.php?title=User:Michiexile/MATH198/Lecture_8&diff=31657User:Michiexile/MATH198/Lecture 82009-11-19T08:13:11Z<p>Jsnx: Case consistency, plox.</p>
<hr />
<div>===Algebras over monads===<br />
<br />
We recall from the last lecture the definition of an Eilenberg-Moore algebra over a monad <math>T = (T, \eta, \mu)</math>: <br />
<br />
'''Definition''' An ''algebra'' over a monad <math>T</math> in a category <math>C</math> (a <math>T</math>-algebra) is a morphism <math>\alpha\in C(TA, A)</math>, such that the diagrams below both commute:<br />
<br />
[[Image:EilenbergMooreUnity.png]]<br />
[[Image:EilenbergMooreAssociativity.png]]<br />
<br />
While a monad corresponds to the imposition of some structure on the objects in a category, an algebra over that monad corresponds to some evaluation of that structure. <br />
<br />
====Example: monoids====<br />
<br />
Let <math>T</math> be the Kleene star monad - the one we get from the adjunction of free and forgetful functors between Monoids and Sets. Then a <math>T</math>-algebra on a set <math>A</math> is equivalent to a monoid structure on <math>A</math>.<br />
<br />
Indeed, if we have a monoid structure on <math>A</math>, given by <math>m:A^2\to A</math> and <math>u:1\to A</math>, we can construct a <math>T</math>-algebra by<br />
:<math>\alpha([]) = u</math><br />
:<math>\alpha([a_1,a_2,\dots,a_n]) = m(a_1,\alpha([a_2,\dots,a_n]))</math><br />
This gives us, indeed, a <math>T</math>-algebra structure on <math>A</math>. Associativity and unity follows from the corresponding properties in the monoid.<br />
<br />
On the other hand, if we have a <math>T</math>-algebra structure on <math>A</math>, we can construct a monoid structure by setting<br />
:<math>u = \alpha([])</math><br />
:<math>m(a,b) = \alpha([a,b])</math> <br />
It is clear that associativity of <math>m</math> follows from the associativity of <math>\alpha</math>, and unitality of <math>u</math> follows from the unitality of <math>\alpha</math>.<br />
<br />
====Example: Vector spaces====<br />
<br />
We have free and forgetful functors <br />
:<math>Set \to^{free} k-Vect \to^{forgetful} Set</math><br />
forming an adjoint pair; where the free functor takes a set <math>S</math> and returns the vector space with basis <math>S</math>; while the forgetful functor takes a vector space and returns the set of all its elements.<br />
<br />
The composition of these yields a monad <math>T</math> in <math>Set</math> taking a set <math>S</math> to the set of all formal linear combinations of elements in <math>S</math>. The monad multiplication takes formal linear combinations of formal linear combinations and multiplies them out:<br />
:<math>3(2v+5w)-5(3v+2w) = 6v+15w-15v-10w = -9v+5w</math><br />
<br />
A <math>T</math>-algebra is a map <math>\alpha: TA\to A</math> that ''acts like a vector space'' in the sense that <math>\alpha(\sum\alpha_i(\sum\beta_jv_j)) = \alpha(\sum\alpha_i\beta_jv_j)</math>.<br />
<br />
We can define <math>\lambda\cdot v = \alpha(\lambda v)</math> and <math>v+w=\alpha(v+w)</math>. The operations thus defined are associative, distributive, commutative, and everything else we could wish for in order to define a vector space - precisely because the operations inside <math>TA</math> are, and <math>\alpha</math> is associative. <br />
<br />
----<br />
<br />
The moral behind these examples is that using monads and monad algebras, we have significant power in defining and studying algebraic structures with categorical and algebraic tools. This paradigm ties in closely with the theory of ''operads'' - which has its origins in topology, but has come to good use within certain branches of universal algebra.<br />
<br />
An (non-symmetric) ''operad'' is a graded set <math>O = \bigoplus_i O_i</math> equipped with composition operations <math>\circ_i: O_n\oplus O_m\to O_{n+m-1}</math> that obey certain unity and associativity conditions. As it turns out, non-symmetric operads correspond to the summands in a monad with polynomial underlying functor, and from a non-symmetric operad we can construct a corresponding monad.<br />
<br />
The designator non-symmetric floats in this text o avoid dealing with the slightly more general theory of symmetric operads - which allow us to resort the input arguments, thus including the symmetrizer of a symmetric monoidal category in the entire definition. <br />
<br />
To read more about these correspondences, I can recommend you start with: the blog posts ''Monads in Mathematics'' here:<br />
[http://embuchestissues.wordpress.com/tag/monads-in-mathematics/]<br />
<br />
<br />
===Algebras over endofunctors===<br />
<br />
Suppose we started out with an endofunctor that is not the underlying functor of a monad - or an endofunctor for which we don't want to settle on a monadic structure. We can still do a lot of the Eilenberg-Moore machinery on this endofunctor - but we don't get quite the power of algebraic specification that monads offer us. At the core, here, lies the lack of associativity for a generic endofunctor - and algebras over endofunctors, once defined, will correspond to non-associative correspondences to their monadic counterparts.<br />
<br />
'''Definition''' For an endofunctor <math>P:C\to C</math>, we define a ''<math>P</math>-algebra'' to be an arrow <math>\alpha\in C(PA,A)</math>.<br />
<br />
A homomorphism of <math>P</math>-algebras <math>\alpha\to\beta</math> is some arrow <math>f:A\to B</math> such that the diagram below commutes:<br />
:[[Image:EilenbergMoorePMorphism.png]]<br />
<br />
This homomorphism definition does not need much work to apply to the monadic case as well.<br />
<br />
====Example: Groups====<br />
<br />
A group is a set <math>G</math> with operations <math>u: 1\to G, i: G\to G, m: G\times G\to G</math>, such that <math>u</math> is a unit for <math>m</math>, <math>m</math> is associative, and <math>i</math> is an inverse.<br />
<br />
Ignoring for a moment the properties, the theory of groups is captured by these three maps, or by a diagram<br />
:[[Image:GroupDiagram.png]]<br />
<br />
We can summarize the diagram as<br />
:<math>1+G+G\times G \mapsto^{[u,i,m]} G</math><br />
and thus recognize that groups are some equationally defined subcategory of the category of <math>T</math>-algebras for the polynomial functor <math>T(X) = 1 + X + X\times X</math>. The subcategory is ''full'', since if we have two algebras <math>\gamma: T(G)\to G</math> and <math>\eta: T(H)\to H</math>, that both lie within the subcategory that fulfills all the additional axioms, then certainly any morphism <math>\gamma\to\eta</math> will be compatible with the structure maps, and thus will be a group homomorphism.<br />
<br />
----<br />
<br />
We shall denote the category of <math>P</math>-algebras in a category <math>C</math> by <math>P-Alg(C)</math>, or just <math>P-Alg</math> if the category is implicitly understood.<br />
<br />
This category is wider than the corresponding concept for a monad. We don't require the kind of associativity we would for a monad - we just lock down the underlying structure. This distinction is best understood with an example: <br />
<br />
The free monoids monad has monoids for its algebras. On the other hand, we can pick out the underlying functor of that monad, forgetting about the unit and multiplication. An algebra over this structure is a slightly more general object: we no longer require <math>(a\cdot b)\cdot c = a\cdot (b\cdot c)</math>, and thus, the theory we get is that of a ''magma''. We have concatenation, but we can't drop the brackets, and so we get something more reminiscent of a binary tree. <br />
<br />
===Initial <math>P</math>-algebras and recursion===<br />
<br />
Consider the polynomical functor <math>P(X) = 1 + X</math> on the category of sets. It's algebras form a category, by the definitions above - and an algebra needs to pick out one special element 0, and one endomorphism T, for a given set.<br />
<br />
What would an initial object in this category of P-algebras look like? It would be an object <math>I</math> equipped with maps <math>1 \to^o I \leftarrow^n I</math>. For any other pair of maps <math>a: 1\to X, s: X\to X</math>, we'd have a unique arrow <math>u: I\to X</math> such that <br />
:[[Image:NNOcommutes.png]]<br />
commutes, or in equations such that<br />
:<math>u(o) = a</math><br />
:<math>u(n(x)) = s(u(x))</math><br />
<br />
Now, unwrapping the definitions in place, we notice that we will have elements <math>o, n(o), n(n(o), \dots</math> in <math>I</math>, and the initiality will force us to not have any ''other'' elements floating around. Also, intiality will prevent us from having any elements not in this minimally forced list.<br />
<br />
We can rename the elements to form something more recognizable - by equating an element in <math>I</math> with the number of applications of <math>n</math> to <math>o</math>. This yields, for us, elements <math>0, 1, 2, \dots</math> with one function that picks out the <math>0</math>, and another that gives us the cussessor.<br />
<br />
This should be recognizable as exactly the natural numbers; with just enough structure on them to make the principle of mathematical induction work: suppose we can prove some statement <math>P(0)</math>, and we can extend a proof of <math>P(n)</math> to <math>P(n+1)</math>. Then induction tells us that the statement holds for all <math>P(n)</math>.<br />
<br />
More importantly, recursive definitions of functions from natural numbers can be performed here by choosing an appropriate algebra mapping to.<br />
<br />
This correspondence between the initial object of <math>P(X) = 1 + X</math> is the reason such an initial object in a category with coproducts and terminal objects is called a ''natural numbers object''. <br />
<br />
For another example, we consider the functor <math>P(X) = 1 + X\times X</math>. <br />
<br />
'''Pop Quiz''' Can you think of a structure with this as underlying defining functor?<br />
<br />
An initial <math>1+X\times X</math>-algebra would be some diagram<br />
:<math>1 \to^o I \leftarrow^m I\times I</math><br />
such that for any other such diagram<br />
:<math>1 \to^a X \leftarrow^* X\times X</math><br />
we have a unique arrow <math>u:I\to X</math> such that<br />
:[[Image:MonoidCommutes.png]]<br />
commutes.<br />
<br />
Unwrapping the definition, working over Sets again, we find we are forced to have some element <math>*</math>, the image of <math>o</math>. Any two elements <math>S,T</math> in the set give rise to some <math>(S,T)</math>, which we can view as being the binary tree<br />
:[[Image:MagmaComposition.png]]<br />
<br />
The same way that we could construct induction as an algebra map from a natural numbers object, we can use this object to construct a tree-shaped induction; and similarily, we can develop what amounts to the theory of ''structural induction'' using these more general approaches to induction.<br />
<br />
====Example of structural induction====<br />
<br />
Using the structure of <math>1+X\times X</math>-algebras we shall prove the following statement:<br />
<br />
'''Proposition''' The number of leaves in a binary tree is one more than the number of internal nodes.<br />
<br />
'''Proof''' We write down the actual Haskell data type for the binary tree initial algebra.<br />
<haskell><br />
data Tree = Leaf | Node Tree Tree<br />
<br />
nLeaves Leaf = 1<br />
nLeaves (Node s t) = nLeaves s + nLeaves t<br />
<br />
nNodes Leaf = 0<br />
nNodes (Node s t) = 1 + nNodes s + nNodes t<br />
</haskell><br />
<br />
Now, it is clear, as a base case, that for the no-nodes tree <hask>Leaf</hask>:<br />
<haskell><br />
nLeaves Leaf = 1 + nNodes Leaf<br />
</haskell><br />
<br />
For the structural induction, now, we consider some binary tree, where we assume the statement to be known for each of the two subtrees. Hence, we have<br />
<haskell><br />
tree = Node s t<br />
<br />
nLeaves s = 1 + nNodes s<br />
nLeaves t = 1 + nNodes t<br />
</haskell><br />
and we may compute<br />
<haskell><br />
nLeaves tree = nLeaves s + nLeaves t <br />
= 1 + nNodes s + 1 + nNodes t <br />
= 2 + nNodes s + nNodes t<br />
<br />
nNodes tree = 1 + nNodes s + nNodes t<br />
</haskell><br />
<br />
Now, since the statement is proven for each of the cases in the structural description of the data, it follows form the principle of structural induction that the proof is finished.<br />
<br />
In order to really nail down what we are doing here, we need to define what we mean by predicates in a strict manner. There is a way to do this using ''fibrations'', but this reaches far outside the scope of this course. For the really interested reader, I'll refer to [http://www.springerlink.com/content/d022nlv03n26nm03/]. <br />
<br />
Another way to do this is to introduce a ''topos'', and work it all out in terms of its ''internal logic'', but again, this reaches outside the scope of this course.<br />
<br />
====Lambek's lemma====<br />
<br />
What we do when we write a recursive data type definition in Haskell ''really'' to some extent is to define a data type as the initial algebra of the corresponding functor. This intuitive equivalence is vindicated by the following <br />
<br />
'''Lemma''' ''Lambek'' If <math>P: C\to C</math> has an initial algebra <math>I</math>, then <math>P(I) = I</math>.<br />
<br />
'''Proof''' Let <math>a: PA\to A</math> be an initial <math>P</math>-algebra. We can apply <math>P</math> again, and get a chain<br />
:<math>PPA \to^{Pa} PA \to^a A</math><br />
We can fill out the diagram<br />
:[[Image:LambekPartialDiagram.png]]<br />
to form the diagram<br />
:[[Image:LambekDiagram.png]]<br />
where <math>f</math> is induced by initiality, since <math>Pa \colon PPA \to PA</math> is also a <math>P</math>-algebra.<br />
<br />
The diagram above commutes, and thus <math>af = 1_{PA}</math> and <math>fa = 1_A</math>. Thus <math>f</math> is an inverse to <math>a</math>. QED.<br />
<br />
Thus, by Lambek's lemma we ''know'' that if <math>P_A(X) = 1 + A\times X</math> then for that <math>P_A</math>, the initial algebra - should it exist - will fulfill<math>I = 1 + A\times I</math>, which in turn is exactly what we write, defining this, in Haskell code: <br />
<haskell><br />
List a = Nil | Cons a List<br />
</haskell><br />
<br />
====Recursive definitions with the unique maps from the initial algebra====<br />
<br />
Consider the following <math>P_A(X)</math>-algebra structure <math>l: P_A(\mathbb N)\to\mathbb N</math> on the natural numbers:<br />
<haskell><br />
l(*) = 0<br />
l(a,n) = 1 + n<br />
</haskell><br />
<br />
We get a unique map <math>f</math> from the initial algebra for <math>P_A(X)</math> (lists of elements of type <math>A</math>) to <math>\mathbb N</math> from this definition. This map will fulfill:<br />
<haskell><br />
f(Nil) = l(*) = 0<br />
f(Cons a xs) = l(a,f(xs)) = 1 + f(xs)<br />
</haskell><br />
which starts taking on the shape of the usual definition of the length of a list:<br />
<haskell><br />
length(Nil) = 0<br />
length(Cons a xs) = 1 + length(xs)<br />
</haskell><br />
<br />
And thus, the machinery of endofunctor algebras gives us a strong method for doing recursive definitions in a theoretically sound manner.<br />
<br />
===Homework===<br />
<br />
Complete credit will be given for 8 of the 13 questions.<br />
<br />
# Find a monad whose algebras are ''associative algebras'': vector spaces with a binary, associative, unitary operation (multiplication) defined on them. Factorize the monad into a free/forgetful adjoint pair.<br />
# Find an endofunctor of <math>Hask</math> whose initial object describes trees that are either binary of ternary at each point, carrying values from some <math>A</math> in the leaves.<br />
# Write an implementation of the monad of vector spaces in Haskell. If this is tricky, restrict the domain of the monad to, say, a 3-element set, and implement the specific example of a 3-dimensional vector space as a monad. Hint: [http://sigfpe.blogspot.com] has written about this approach.<br />
# Find a <math>X\mapsto 1+A\times X</math>-algebra <math>L</math> such that the unique map from the initial algebra <math>I</math> to <math>L</math> results in the function that will reverse a given list.<br />
# Find a <math>X\mapsto 1+A\times X</math>-algebra structure on the object <math>1+A</math> that will pick out the first element of a list, if possible.<br />
# Find a <math>X\mapsto \mathbb N+X\times X</math>-algebra structure on the object <math>\mathbb N</math> that will pick out the sum of the leaf values for the binary tree in the initial object.<br />
# Complete the proof of Lambek's lemma by proving the diagram commutes.<br />
# * We define a ''coalgebra'' for an endofunctor <math>T</math> to be some arrow <math>\gamma: A \to TA</math>. If <math>T</math> is a comonad - i.e. equipped with a counit <math>\epsilon: T\to 1</math> and a cocomposition <math>\Delta: T\to T\times T</math>, then we define a coalgebra for the comonad <math>T</math> to additionally fulfill <math>\gamma\circ T\gamma = \gamma\circ\Delta</math> (compatibility) and <math>\epsilon_A\circ\gamma = 1_A</math> (counitality).<br />
## (2pt) Prove that if <math>T</math> is an endofunctor, then if <math>T</math> has an initial algebra, then it is a coalgebra. Does <math>T</math> necessarily have a final coalgebra?<br />
## (2pt) Prove that if <math>U,F</math> are an adjoint pair, then <math>FU</math> forms a comonad.<br />
## (2pt) Describe a final coalgebra over the comonad formed from the free/forgetful adjunction between the categories of Monoids and Sets.<br />
## (2pt) Describe a final coalgebra over the endofunctor <math>P(X) = 1 + X</math>.<br />
## (2pt) Describe a final coalgebra over the endofunctor <math>P(X) = 1 + A\times X</math>.<br />
## (2pt) Prove that if <math>c: C\to PC</math> is a final coalgebra for an endofunctor <math>P:C\to C</math>, then <math>c</math> is an isomorphism.</div>Jsnxhttps://wiki.haskell.org/index.php?title=User:Michiexile/MATH198/Lecture_6&diff=31391User:Michiexile/MATH198/Lecture 62009-11-02T03:25:34Z<p>Jsnx: MOAR functions</p>
<hr />
<div>IMPORTANT NOTE: THESE NOTES ARE STILL UNDER DEVELOPMENT. PLEASE WAIT UNTIL AFTER THE LECTURE WITH HANDING ANYTHING IN, OR TREATING THE NOTES AS READY TO READ.<br />
<br />
===Useful limits and colimits=== <br />
<br />
With the tools of limits and colimits at hand, we can start using these to introduce more category theoretical constructions - and some of these turn out to correspond to things we've seen in other areas. <br />
<br />
Possibly among the most important are the equalizers and coequalizers (with kernel (nullspace) and images as special cases), and the pullbacks and pushouts (with which we can make explicit the idea of inverse images of functions). <br />
<br />
One useful theorem to know about is: <br />
<br />
'''Theorem''' The following are equivalent for a category <math>C</math>: <br />
* <math>C</math> has all finite limits. <br />
* <math>C</math> has all finite products and all equalizers. <br />
* <math>C</math> has all pullbacks and a terminal object. <br />
<br />
Also, the following dual statements are equivalent: <br />
* <math>C</math> has all finite colimits. <br />
* <math>C</math> has all finite coproducts and all coequalizers. <br />
* <math>C</math> has all pushouts and an initial object. <br />
<br />
For this theorem, we can replace ''finite'' with any other cardinality in every place it occurs, and we will still get a valid theorem. <br />
<br />
====Equalizer, coequalizer==== Consider the ''equalizer diagram'': <br />
[[Image:EqualizerDiagram.png]] <br />
<br />
A limit over this diagram is an object <math>C</math> and arrows to all diagram objects. The commutativity conditions for the arrows defined force for us <math>fp_A = p_B = gp_A</math>, and thus, keeping this enforced equation in mind, we can summarize the cone diagram as: <br />
<br />
[[Image:EqualizerCone.png]] <br />
<br />
Now, the limit condition tells us that this is the least restrictive way we can map into <math>A</math> with some map <math>p</math> such that <math>fp = gp</math>, in that every other way we could map in that way will factor through this way. <br />
<br />
As usual, it is helpful to consider the situation in Set to make sense of any categorical definition: and the situation there is helped by the generalized element viewpoint: the limit object <math>C</math> is one representative of a subobject of <math>A</math> that for the case of Set contains all <math>x\in A: f(x) = g(x)</math>. <br />
<br />
Hence the word we use for this construction: the limit of the diagram above is the ''equalizer of <math>f, g</math>''. It captures the idea of a maximal subset unable to distinguish two given functions, and it introduces a categorical way to define things by equations we require them to respect. <br />
<br />
One important special case of the equalizer is the ''kernel'': in a category with a null object, we have a distinguished, unique, member <math>0</math> of any homset given by the compositions of the unique arrows to and from the null object. We define ''the kernel'' <math>Ker(f)</math> of an arrow <math>f</math> to be the equalizer of <math>f, 0</math>. Keeping in mind the arrow-centric view on categories, we tend to denote the arrow from <math>Ker(f)</math> to the source of <math>f</math> by <math>ker(f)</math>. <br />
<br />
In the category of vector spaces, and linear maps, the map <math>0</math> really is the constant map taking the value <math>0</math> everywhere. And the kernel of a linear map <math>f:U\to V</math> is the equalizer of <math>f,0</math>. Thus it is some vector space <math>W</math> with a map <math>i:W\to U</math> such that <math>fi = 0i = 0</math>, and any other map that fulfills this condition factors through <math>W</math>. Certainly the vector space <math>\{u\in U: f(u)=0\}</math> fulfills the requisite condition, nothing larger will do, since then the map composition wouldn't be 0, and nothing smaller will do, since then the maps factoring this space through the smaller candidate would not be unique. <br />
<br />
Hence, <math>Ker(f) = \{u\in U: f(u) = 0\}</math> just like we might expect. <br />
<br />
Dually, we get the ''coequalizer'' as the colimit of the equalizer diagram. <br />
<br />
A coequalizer <br />
<br />
[[Image:CoequalizerCoCone.png]] <br />
<br />
has to fulfill that <math>i_Bf = i_A = i_Bg</math>. Thus, writing <math>q=i_B</math>, we get an object with an arrow (actually, an epimorphism out of <math>B</math>) that identifies <math>f</math> and <math>g</math>. Hence, we can think of <math>i_B:B\to Q</math> as catching the notion of inducing equivalence classes from the functions. <br />
<br />
This becomes clear if we pick out one specific example: let <math>R\subseteq X\times X</math> be an equivalence relation, and consider the diagram <br />
<br />
[[Image:EquivCoequalizer.png]] <br />
<br />
where <math>r_1</math> and <math>r_2</math> are given by the projection of the inclusion of the relation into the product onto either factor. Then, the coequalizer of this setup is an object <math>X/R</math> such that whenever <math>x\sim_R y</math>, then <math>q(x)=q(y)</math>. <br />
<br />
<br />
====Pullbacks====<br />
<br />
The preimage <math>f^{-1}(T)</math> of a subset <math>T\subseteq S</math> along a function <math>f:U\to S</math> is a maximal subset <math>V\subseteq U</math> such that for every <math>v\in V: f(v)\in T</math>.<br />
<br />
We recall that subsets are given by (equivalence classes of) monics, and thus we end up being able to frame this in purely categorical terms. Given a diagram like this:<br />
<br />
[[Image:PreimageDiagram.png]]<br />
<br />
where <math>i</math> is a monomorphism representing the subobject, we need to find an object <math>V</math> with a monomorphism injecting it into <math>U</math> such that the map <math>\bar fj: V\to S</math> factors through <math>T</math>. Thus we're looking for dotted maps making the diagram commute, in a universal manner.<br />
<br />
The maximality of the subobject means that any other subobject of <math>U</math> that can be factored through <math>T</math> should factor through <math>V</math>.<br />
<br />
----<br />
<br />
Suppose <math>U, V</math> are subsets of some set <math>W</math>. Their intersection <math>U\cap V</math> is a subset of <math>U</math>, a subset of <math>V</math> and a subset of <math>W</math>, maximal with this property.<br />
<br />
Translating into categorical language, we can pick representatives for all subobjects in the definition, we get a diagram with all monomorphisms:<br />
<br />
[[Image:IntersectionDiagram.png]]<br />
<br />
where we need the inclusion of <math>U\cap V</math> into <math>W</math> over <math>U</math> is the same as the inclusion over <math>V</math>.<br />
<br />
----<br />
<br />
'''Definition''' A ''pullback'' of two maps <math>A \rightarrow^f C \leftarrow^g B</math> is the limit of these two maps, thus:<br />
<br />
[[Image:PullbackDiagram.png]]<br />
<br />
By the definition of a limit, this means that the pullback is an object <math>P</math> with maps <math>\bar f: P\to B</math>, <math>\bar g: P\to A</math> and <math>f\bar g = g\bar f : P\to C</math>, such that any other such object factors through this.<br />
<br />
For the diagram <math>U\rightarrow^f S \leftarrow^i T</math>, with <math>i:T\to S</math> one representative monomorphism for the subobject, we get precisely the definition above for the inverse image.<br />
<br />
For the diagram <math>U\rightarrow W \leftarrow V</math> with both map monomorphisms representing their subobjects, the pullback is the intersection.<br />
<br />
====Pushouts====<br />
<br />
Often, especially in geometry and algebra, we construct new structures by gluing together old structures along substructures. Possibly the most popularly known example is the M&ouml;bius band: we take a strip of paper, twist it once and glue the ends together.<br />
<br />
Similarily, in algebraic contexts, we can form ''amalgamated products'' that do roughly the same.<br />
<br />
All these are instances of the dual to the pullback:<br />
<br />
'''Definition''' A ''pushout'' of two maps <math>A\leftarrow^f C\rightarrow^g B</math> is the co-limit of these two maps, thus:<br />
<br />
[[Image:PushoutDiagram.png]]<br />
<br />
Hence, the pushout is an object <math>D</math> such that <math>C</math> maps to the same place both ways, and so that, contingent on this, it behaves much like a coproduct. <br />
<br />
===Free and forgetful functors===<br />
<br />
Recall how we defined a free monoid as all strings of some alphabet, with concatenation of strings the monoidal operation. And recall how we defined the free category on a graph as the category of paths in the graph, with path concatenation as the operation.<br />
<br />
The reason we chose the word ''free'' to denote both these cases is far from a coincidence: by this point nobody will be surprised to hear that we can unify the idea of generating the most general object of a particular algebraic structure into a single categorical idea.<br />
<br />
The idea of the free constructions, classically, is to introduce as few additional relations as possible, while still generating a valid object of the appropriate type, given a set of generators we view as placeholders, as symbols. Having a minimal amount of relations allows us to introduce further relations later, by imposing new equalities by mapping with surjections to other structures.<br />
<br />
One of the first observations in each of the cases we can do is that such a map ends up being completely determined by where the generators go - the symbols we use to generate. And since the free structure is made to fulfill the axioms of whatever structure we're working with, these generators combine, even after mapping to some other structure, in a way compatible with all structure.<br />
<br />
To make solid categorical sense of this, however, we need to couple the construction of a free algebraic structure from a set (or a graph, or...) with another construction: we can define the ''forgetful functor'' from monoids to sets by just picking out the elements of the monoid as a set; and from categories to graph by just picking the underlying graph, and forgetting about the compositions of arrows.<br />
<br />
Now we have what we need to pinpoint just what kind of a functor the ''free widget generated by''-construction does. It's a functor <math>F: C\to D</math>, coupled with a forgetful functor <math>U: D\to C</math> such that any map <math>S\to U(N)</math> in <math>C</math> induces one unique mapping <math>F(S)\to N</math> in <math>D</math>.<br />
<br />
For the case of monoids and sets, this means that if we take our generating set, and map it into the set of elements of another monoid, this generates a unique mapping of the corresponding monoids.<br />
<br />
This is all captured by a similar kind of diagrams and uniquely existing maps argument as the previous object or morphism properties were defined with. We'll show the definition for the example of monoids.<br />
<br />
'''Definition''' A ''free'' monoid on a generating set <math>X</math> is a monoid <math>F(X)</math> such that there is an inclusion <math>i_X: X\to UF(X)</math> and for every function <math>f : X\to U(M)</math> for some other monoid <math>M</math>, there is a unique homomorphism <math>g:F(X)\to M</math> such that <math>f=U(g) i_X</math>, or in other words such that this diagram commutes:<br />
<br />
[[Image:FreeMonoid.png]]<br />
<br />
We can construct a map <math>\phi:Hom_{Mon}(F(X),M) \to Hom_{Set}(X,U(M))</math> by <math>\phi: g\mapsto U(g)\circ i_X</math>. The above definition says that this map is an isomorphism.<br />
<br />
===Adjunctions===<br />
<br />
Modeling on the way we construct free and forgetful functors, we can form a powerful categorical concept, which ends up generalizing much of what we've already seen - and also leads us on towards monads. <br />
<br />
We draw on the definition above of free monoids to give a preliminary definition. This will be replaced later by an equivalent definition that gives more insight.<br />
<br />
'''Definition''' A pair of functors, <br />
<br />
[[Image:AdjointPair.png]]<br />
<br />
is called an ''adjoint pair'' or an ''adjunction'', with <math>F</math> called the ''left adjoint'' and <math>U</math> called the ''right adjoint'' if there is natural transformation <math>\eta: 1\to UF</math>, and for every <math>f:A\to U(B)</math>, there is a unique <math>g: F(A)\to B</math> such that the diagram below commutes.<br />
<br />
[[Image:AdjointDefinition.png]]<br />
<br />
The natural transformation <math>\eta</math> is called the ''unit'' of the adjunction. <br />
<br />
This definition, however, has a significant amount of asymmetry: we can start with some <math>f:A\to U(B)</math> and generate a <math>g: F(A)\to B</math>, while there are no immediate guarantees for the other direction. However, there is a proposition we can prove leading us to a more symmetric statement:<br />
<br />
'''Proposition''' For categories and functors<br />
<br />
[[Image:AdjointPair.png]]<br />
<br />
the following conditions are equivalent:<br />
# <math>F</math> is left adjoint to <math>U</math>.<br />
# For any <math>c\in C_0</math>, <math>d\in D_0</math>, there is an isomorphism <math>\phi: Hom_D(Fc, d) \to Hom_C(c,Ud)</math>, natural in both <math>c</math> and <math>d</math>.<br />
moreover, the two conditions are related by the formulas<br />
* <math>\phi(g) = U(g) \circ \eta_c</math><br />
* <math>\eta_c = \phi(1_{Fc})</math><br />
<br />
'''Proof sketch'''<br />
For (1 implies 2), the isomorphism is given by the end of the statement, and it is an isomorphism exactly because of the unit property - viz. that every <math>f:A\to U(B)</math> generates a unique <math>g: F(A)\to B</math>.<br />
<br />
Naturality follows by building the naturality diagrams<br />
<br />
[[Image:AdjointNaturalFirst.png]] [[Image:AdjointNaturalSecond.png]]<br />
<br />
and chasing through with a <math>f: Fc\to d</math>.<br />
<br />
For (2 implies 1), we start out with a natural isomorphism <math>\phi</math>. We find the necessary natural transformation <math>\eta_c</math> by considering <math>\phi: Hom(Fc,Fc) \to Hom(c, UFc)</math>.<br />
<br />
QED. <br />
<br />
By dualizing the proof, we get the following statement: <br />
<br />
'''Proposition''' For categories and functors<br />
<br />
[[Image:AdjointPair.png]]<br />
<br />
the following conditions are equivalent:<br />
# For any <math>c\in C_0</math>, <math>d\in D_0</math>, there is an isomorphism <math>\phi: Hom_D(Fc, d) \to Hom_C(c,Ud)</math>, natural in both <math>c</math> and <math>d</math>.<br />
# There is a natural transformation <math>\epsilon: FU \to 1_D</math> with the property that for any <math>g: F(c) \to d</math> there is a unique <math>f: c\to U(d)</math> such that <math>g = \epsilon_D\circ F(f)</math>, as in the diagram<br />
<br />
[[Image:AdjointDualDefinition.png]]<br />
<br />
moreover, the two conditions are related by the formulas<br />
* <math>\psi(f) = \epsilon_D\circ F(f)</math><br />
* <math>\epsilon_d = \psi(1_{Ud})</math><br />
<br />
where <math>\psi = \phi^{-1}</math>. <br />
<br />
Hence, we have an equivalent definition with higher generality, more symmetry and more ''horsepower'', as it were:<br />
<br />
'''Definition''' An ''adjunction'' consists of functors<br />
<br />
[[Image:AdjointPair.png]]<br />
<br />
and a natural isomorphism<br />
<br />
[[Image:AdjointIso.png]]<br />
<br />
The ''unit'' <math>\eta</math> and the ''counit'' <math>\epsilon</math> of the adjunction are natural transformations given by:<br />
* <math>\eta: 1_C\to UF: \eta_c = \phi(1_{Fc})</math><br />
* <math>\epsilon: FU\to 1_D: \epsilon_d = \psi(1_{Ud})</math>.<br />
<br />
----<br />
<br />
Some of the examples we have had difficulties fitting into the limits framework show up as adjunctions:<br />
<br />
The ''free'' and ''forgetful'' functors are adjoints; and indeed, a more natural definition of what it means to be free is that it is a left adjoint to some forgetful functor.<br />
<br />
Curry and uncurry, in the definition of an exponential object are an adjoint pair. The functor <math>-\times A: X\mapsto X\times A</math> has right adjoint <math>-^A: Y\mapsto Y^A</math>. <br />
<br />
====Notational aid====<br />
<br />
One way to write the adjoint is as a ''bidirectional rewrite rule'':<br />
<br />
<math>\frac{F(X) \to Y}{X\to G(Y)}</math>, <br />
<br />
where the statement is that the hom sets indicated by the upper and lower arrow, respectively, are transformed into each other by the unit and counit respectively. The left adjoint is the one that has the functor application on the left hand side of this diagram, and the right adjoint is the one with the functor application to the right.<br />
<br />
<br />
<br />
<br />
===Homework===<br />
<br />
Complete homework is 6 out of 11 exercises.<br />
<br />
# Prove that an equalizer is a monomorphism.<br />
# Prove that a coequalizer is an epimorphism.<br />
# Prove that given any relation <math>R\subseteq X\times X</math>, its completion to an equivalence relation is the kernel of the coequalizer of the component maps of the relation<br />
# Prove that if the right arrow in a pullback square is a mono, then so is the left arrow. Thus the intersection as a pullback really is a subobject.<br />
# Prove that if both the arrows in the pullback 'corner' are mono, then the arrows of the pullback cone are all mono.<br />
# What is the pullback in the category of posets?<br />
# What is the pushout in the category of posets?<br />
# Prove that the exponential and the product functors above are adjoints. What are the unit and counit?<br />
# (worth 4pt) Consider the unique functor <math>!:C\to 1</math> to the terminal category.<br />
## Does it have a left adjoint? What is it?<br />
## Does it have a right adjoint? What is it?<br />
# * Prove the propositions in the text.<br />
# (worth 4pt) Suppose <br />
:[[Image:AdjointPair.png]] <br />
:is an adjoint pair. Find a natural transformation <math>FUF\to F</math>. Conclude that there is a natural transformation <math>\mu: UFUF\to UF</math>. Prove that this is associative, in other words that the diagram<br />
:[[Image:AdjointMuAssociative.png]]<br />
:commutes. Prove that the unit of the adjunction forms a unit for this <math>\mu</math>, in other words, that the diagram<br />
:[[Image:AdjointMuUnit.png]]<br />
:commutes.</div>Jsnxhttps://wiki.haskell.org/index.php?title=User:Michiexile/MATH198/Lecture_4&diff=30985User:Michiexile/MATH198/Lecture 42009-10-22T06:07:04Z<p>Jsnx: </p>
<hr />
<div>===Product===<br />
<br />
Recall the construction of a cartesian product of two sets: <math>A\times B=\{(a,b) : a\in A, b\in B\}</math>. We have functions <math>p_A:A\times B\to A</math> and <math>p_B:A\times B\to B</math> extracting the two sets from the product, and we can take any two functions <math>f:A\to A'</math> and <math>g:B\to B'</math> and take them together to form a function <math>f\times g:A\times B\to A'\times B'</math>.<br />
<br />
Similarly, we can form the type of pairs of Haskell types: <hask>Pair s t = (s,t)</hask>. For the pair type, we have canonical functions <hask>fst :: (s,t) -> s</hask> and <hask>snd :: (s,t) -> t</hask> extracting the components. And given two functions <hask>f :: s -> s'</hask> and <hask>g :: t -> t'</hask>, there is a function <hask>f *** g :: (s,t) -> (s',t')</hask>.<br />
<br />
An element of the pair is completely determined by the two elements included in it. Hence, if we have a pair of generalized elements <math>q_1:V\to A</math> and <math>q_2:V\to B</math>, we can find a unique generalized element <math>q:V\to A\times B</math> such that the projection arrows on this gives us the original elements back.<br />
<br />
This argument indicates to us a possible definition that avoids talking about elements in sets in the first place, and we are lead to the<br />
<br />
'''Definition''' A ''product'' of two objects <math>A,B</math> in a category <math>C</math> is an object <math>A\times B</math> equipped with arrows <math>A \leftarrow^{p_1} A\times B\rightarrow^{p_2} B</math> such that for any other object <math>V</math> with arrows <math>A \leftarrow^{q_1} V \rightarrow^{q_2} B</math>, there is a unique arrow <math>V\to A\times B</math> such that the diagram<br />
<br />
[[Image:AxBdiagram.png]]<br />
<br />
commutes. The diagram <math>A \leftarrow^{p_1} A\times B\rightarrow^{p_2} B</math> is called a ''product cone'' if it is a diagram of a product with the ''projection arrows'' from its definition.<br />
<br />
In the category of sets, the unique map is given by <math>q(v) = (q_1(v),q_2(v))</math>. In the Haskell category, it is given by the combinator <hask>(&&&) :: (a -> b) -> (a -> c) -> a -> (b,c)</hask>.<br />
<br />
We tend to talk about ''the product''. The justification for this lies in the first interesting<br />
<br />
'''Proposition''' If <math>P</math> and <math>P'</math> are both products for <math>A,B</math>, then they are isomorphic.<br />
<br />
'''Proof''' Consider the diagram<br />
<br />
[[Image:ProductIsomorphismDiagram.png]]<br />
<br />
Both vertical arrows are given by the product property of the two product cones involved. Their compositions are endo-arrows of <math>P, P'</math>, such that in each case, we get a diagram like<br />
<br />
[[Image:AxBdiagram.png]]<br />
<br />
with <math>V=A\times B=P</math> (or <math>P'</math>), and <math>q_1=p_1, q_2=p_2</math>. There is, by the product property, only one endoarrow that can make the diagram work - but both the composition of the two arrows, and the identity arrow itself, make the diagram commute. Therefore, the composition has to be the identity. QED.<br />
<br />
We can expand the binary product to higher order products easily - instead of pairs of arrows, we have families of arrows, and all the diagrams carry over to the larger case.<br />
<br />
====Binary functions====<br />
<br />
Functions into a product help define the product in the first place, and function as elements of the product. Functions ''from'' a product, on the other hand, allow us to put a formalism around the idea of functions of several variables.<br />
<br />
So a function of two variables, of types <hask>A</hask> and <hask>B</hask> is a function <hask>f :: (A,B) -> C</hask>. The Haskell idiom for the same thing, <hask>A -> B -> C</hask> as a function taking one argument and returning a function of a single variable; as well as the <hask>curry</hask>/<hask>uncurry</hask> procedure is tightly connected to this viewpoint, and will reemerge below, as well as when we talk about adjunctions later on.<br />
<br />
===Coproduct===<br />
<br />
The product came, in part, out of considering the pair construction. One alternative way to write the <hask>Pair a b</hask> type is:<br />
<haskell><br />
data Pair a b = Pair a b<br />
</haskell><br />
and the resulting type is isomorphic, in Hask, to the product type we discussed above.<br />
<br />
This is one of two basic things we can do in a <hask>data</hask> type declaration, and corresponds to the ''record'' types in Computer Science jargon.<br />
<br />
The other thing we can do is to form a ''union'' type, by something like<br />
<haskell><br />
data Union a b = Left a | Right b<br />
</haskell><br />
which takes on either a value of type <hask>a</hask> or of type <hask>b</hask>, depending on what constructor we use. <br />
<br />
This type guarantees the existence of two functions<br />
<haskell><br />
Left :: a -> Union a b<br />
Right :: b -> Union a b<br />
</haskell><br />
<br />
Similarly, in the category of sets we have the disjoint union <math>S\coprod T = S\times 0 \cup T \times 1</math>, which also comes with functions <math>i_S: S\to S\coprod T, i_T: T\to S\coprod T</math>.<br />
<br />
We can use all this to mimic the product definition. The directions of the inclusions indicate that we may well want the dualization of the definition. Thus we define:<br />
<br />
'''Definition''' A ''coproduct'' <math>A+B</math> of objects <math>A, B</math> in a category <math>C</math> is an object equipped with arrows <math>A \rightarrow^{i_1} A+B \leftarrow^{i_2} B</math> such that for any other object <math>V</math> with arrows <math>A\rightarrow^{q_1} V\leftarrow^{q_2} B</math>, there is a unique arrow <math>A+B\to V</math> such that the diagram<br />
<br />
[[Image:A-Bdiagram.png]]<br />
<br />
commutes. The diagram <math>A \rightarrow^{i_1} A+B \leftarrow^{i_2} B</math> is called a ''coproduct cocone'', and the arrows are ''inclusion arrows''.<br />
<br />
For sets, we need to insist that instead of just any <math>S\times 0</math> and <math>T\times 1</math>, we need the specific construction taking pairs for the coproduct to work out well. The issue here is that the categorical product is not defined as one single construction, but rather from how it behaves with respect to the arrows involved. <br />
<br />
With this caveat, however, the coproduct in Set really is the disjoint union sketched above.<br />
<br />
For Hask, the coproduct is the type construction of <hask>Union</hask> above - more usually written <hask>Either a b</hask>.<br />
<br />
And following closely in the dualization of the things we did for products, there is a first <br />
<br />
'''Proposition''' If <math>C, C'</math> are both coproducts for some pair <math>A, B</math> in a category <math>D</math>, then they are isomorphic.<br />
<br />
The proof follows the exact pattern of the corresponding proposition for products.<br />
<br />
===Algebra of datatypes===<br />
<br />
Recall from [[User:Michiexile/MATH198/Lecture_3|Lecture 3]] that we can consider endofunctors as container datatypes.<br />
Some of the more obvious such container datatypes include:<br />
<haskell><br />
data 1 a = Empty<br />
data T a = T a<br />
</haskell><br />
These being the data type that has only one single element and the data type that has exactly one value contained.<br />
<br />
Using these, we can generate a whole slew of further datatypes. First off, we can generate a data type with any finite number of elements by <math>n = 1 + 1 + \dots + 1</math> (<math>n</math> times). Remember that the coproduct construction for data types allows us to know which summand of the coproduct a given part is in, so the single elements in all the <hask>1</hask>s in the definition of <hask>n</hask> here are all distinguishable, thus giving the final type the required number of elements.<br />
Of note among these is the data type <hask>Bool = 2</hask> - the Boolean data type, characterized by having exactly two elements.<br />
<br />
Furthermore, we can note that <math>1\times T = T</math>, with the isomorphism given by the maps<br />
<haskell><br />
f (Empty, T x) = T x<br />
g (T x) = (Empty, T x)<br />
</haskell><br />
<br />
Thus we have the capacity to ''add'' and ''multiply'' types with each other. We can verify, for any types <math>A,B,C</math><br />
<math>A\times(B+C) = A\times B + A\times C</math><br />
<br />
We can thus make sense of types like <math>T^3+2T^2</math> (either a triple of single values, or one out of two tagged pairs of single values).<br />
<br />
This allows us to start working out a calculus of data types with versatile expression power. We can produce recursive data type definitions by using equations to define data types, that then allow a direct translation back into Haskell data type definitions, such as:<br />
<br />
<math>List = 1 + T\times List</math><br />
<br />
<math>BinaryTree = T+T\times BinaryTree\times BinaryTree</math><br />
<br />
<math>TernaryTree = T+T\times TernaryTree\times TernaryTree\times TernaryTree</math><br />
<br />
<math>GenericTree = T+T\times (List\circ GenericTree)</math><br />
<br />
The real power of this way of rewriting types comes in the recognition that we can use algebraic methods to reason about our data types. For instance:<br />
<br />
<haskell><br />
List = 1 + T * List <br />
= 1 + T * (1 + T * List) <br />
= 1 + T * 1 + T * T* List <br />
= 1 + T + T * T * List<br />
</haskell><br />
<br />
so a list is either empty, contains one element, or contains at least two elements. Using, though, ideas from the theory of power series, or from continued fractions, we can start analyzing the data types using steps on the way that seem completely bizarre, but arriving at important property. Again, an easy example for illustration:<br />
<br />
<haskell><br />
List = 1 + T * List -- and thus<br />
List - T * List = 1 -- even though (-) doesn't make sense for data types<br />
(1 - T) * List = 1 -- still ignoring that (-)...<br />
List = 1 / (1 - T) -- even though (/) doesn't make sense for data types<br />
= 1 + T + T*T + T*T*T + ... -- by the geometric series identity<br />
</haskell><br />
and hence, we can conclude - using formally algebraic steps in between - that a list by the given definition consists of either an empty list, a single value, a pair of values, three values, et.c.<br />
<br />
At this point, I'd recommend anyone interested in more perspectives on this approach to data types, and thinks one may do with them, to read the following references:<br />
<br />
====Blog posts and Wikipages====<br />
<br />
The ideas in this last section originate in a sequence of research papers from Conor McBride - however, these are research papers in logic, and thus come with all the quirks such research papers usually carry. Instead, the ideas have been described in several places by various blog authors from the Haskell community - which make for a more accessible but much less strict read.<br />
<br />
* http://en.wikibooks.org/wiki/Haskell/Zippers -- On zippers, and differentiating types<br />
* http://blog.lab49.com/archives/3011 -- On the polynomial data type calculus<br />
* http://blog.lab49.com/archives/3027 -- On differentiating types and zippers<br />
* http://comonad.com/reader/2008/generatingfunctorology/ -- Different recursive type constructions<br />
* http://strictlypositive.org/slicing-jpgs/ -- Lecture slides for similar themes.<br />
* http://blog.sigfpe.com/2009/09/finite-differences-of-types.html -- Finite differences of types - generalizing the differentiation approach.<br />
* http://homepage.mac.com/sigfpe/Computing/fold.html -- Develops the underlying theory for our algebra of datatypes in some detail.<br />
<br />
===Homework===<br />
<br />
Complete points for this homework consists of 4 out of 5 exercises. Partial credit is given.<br />
<br />
# What are the products in the category <math>C(P)</math> of a poset <math>P</math>? What are the coproducts?<br />
# Prove that any two coproducts are isomorphic.<br />
# Prove that any two exponentials are isomorphic.<br />
# Write down the type declaration for at least two of the example data types from the section of the algebra of datatypes, and write a <hask>Functor</hask> implementation for each.<br />
# * Read up on Zippers and on differentiating data structures. Find the derivative of List, as defined above. Prove that <math>\partial List = List \times List</math>. Find the derivatives of BinaryTree, and of GenericTree.</div>Jsnxhttps://wiki.haskell.org/index.php?title=User:Michiexile/MATH198/Lecture_4&diff=30984User:Michiexile/MATH198/Lecture 42009-10-22T05:17:12Z<p>Jsnx: Spacing, redundancies.</p>
<hr />
<div>===Product===<br />
<br />
Recall the construction of a cartesian product of two sets: <math>A\times B=\{(a,b) : a\in A, b\in B\}</math>. We have functions <math>p_A:A\times B\to A</math> and <math>p_B:A\times B\to B</math> extracting the two sets from the product, and we can take any two functions <math>f:A\to A'</math> and <math>g:B\to B'</math> and take them together to form a function <math>f\times g:A\times B\to A'\times B'</math>.<br />
<br />
Similarly, we can form the type of pairs of Haskell types: <hask>Pair s t = (s,t)</hask>. For the pair type, we have canonical functions <hask>fst :: (s,t) -> s</hask> and <hask>snd :: (s,t) -> t</hask> extracting the components. And given two functions <hask>f :: s -> s'</hask> and <hask>g :: t -> t'</hask>, there is a function <hask>f *** g :: (s,t) -> (s',t')</hask>.<br />
<br />
An element of the pair is completely determined by the two elements included in it. Hence, if we have a pair of generalized elements <math>q_1:V\to A</math> and <math>q_2:V\to B</math>, we can find a unique generalized element <math>q:V\to A\times B</math> such that the projection arrows on this gives us the original elements back.<br />
<br />
This argument indicates to us a possible definition that avoids talking about elements in sets in the first place, and we are lead to the<br />
<br />
'''Definition''' A ''product'' of two objects <math>A,B</math> in a category <math>C</math> is an object <math>A\times B</math> equipped with arrows <math>A \leftarrow^{p_1} A\times B\rightarrow^{p_2} B</math> such that for any other object <math>V</math> with arrows <math>A \leftarrow^{q_1} V \rightarrow^{q_2} B</math>, there is a unique arrow <math>V\to A\times B</math> such that the diagram<br />
<br />
[[Image:AxBdiagram.png]]<br />
<br />
commutes. The diagram <math>A \leftarrow^{p_1} A\times B\rightarrow^{p_2} B</math> is called a ''product cone'' if it is a diagram of a product with the ''projection arrows'' from its definition.<br />
<br />
In the category of sets, the unique map is given by <math>q(v) = (q_1(v),q_2(v))</math>. In the Haskell category, it is given by the combinator <hask>(&&&) :: (a -> b) -> (a -> c) -> a -> (b,c)</hask>.<br />
<br />
We tend to talk about ''the product''. The justification for this lies in the first interesting<br />
<br />
'''Proposition''' If <math>P</math> and <math>P'</math> are both products for <math>A,B</math>, then they are isomorphic.<br />
<br />
'''Proof''' Consider the diagram<br />
<br />
[[Image:ProductIsomorphismDiagram.png]]<br />
<br />
Both vertical arrows are given by the product property of the two product cones involved. Their compositions are endo-arrows of <math>P, P'</math>, such that in each case, we get a diagram like<br />
<br />
[[Image:AxBdiagram.png]]<br />
<br />
with <math>V=A\times B=P</math> (or <math>P'</math>), and <math>q_1=p_1, q_2=p_2</math>. There is, by the product property, only one endoarrow that can make the diagram work - but both the composition of the two arrows, and the identity arrow itself, make the diagram commute. Therefore, the composition has to be the identity. QED.<br />
<br />
We can expand the binary product to higher order products easily - instead of pairs of arrows, we have families of arrows, and all the diagrams carry over to the larger case.<br />
<br />
====Binary functions====<br />
<br />
Functions into a product help define the product in the first place, and function as elements of the product. Functions ''from'' a product, on the other hand, allow us to put a formalism around the idea of functions of several variables.<br />
<br />
So a function of two variables, of types <hask>A</hask> and <hask>B</hask> is a function <hask>f :: (A,B) -> C</hask>. The Haskell idiom for the same thing, <hask>A -> B -> C</hask> as a function taking one argument and returning a function of a single variable; as well as the <hask>curry</hask>/<hask>uncurry</hask> procedure is tightly connected to this viewpoint, and will reemerge below, as well as when we talk about adjunctions later on.<br />
<br />
===Coproduct===<br />
<br />
The product came, in part, out of considering the pair construction. One alternative way to write the <hask>Pair a b</hask> type is:<br />
<haskell><br />
data Pair a b = Pair a b<br />
</haskell><br />
and the resulting type is isomorphic, in Hask, to the product type we discussed above.<br />
<br />
This is one of two basic things we can do in a <hask>data</hask> type declaration, and corresponds to the ''record'' types in Computer Science jargon.<br />
<br />
The other thing we can do is to form a ''union'' type, by something like<br />
<haskell><br />
data Union a b = Left a | Right b<br />
</haskell><br />
which takes on either a value of type <hask>a</hask> or of type <hask>b</hask>, depending on what constructor we use. <br />
<br />
This type guarantees the existence of two functions<br />
<haskell><br />
Left :: a -> Union a b<br />
Right :: b -> Union a b<br />
</haskell><br />
<br />
Similarly, in the category of sets we have the disjoint union <math>S\coprod T = S\times 0 \cup T \times 1</math>, which also comes with functions <math>i_S: S\to S\coprod T, i_T: T\to S\coprod T</math>.<br />
<br />
We can use all this to mimic the product definition. The directions of the inclusions indicate that we may well want the dualization of the definition. Thus we define:<br />
<br />
'''Definition''' A ''coproduct'' <math>A+B</math> of objects <math>A, B</math> in a category <math>C</math> is an object equipped with arrows <math>A \rightarrow^{i_1} A+B \leftarrow^{i_2} B</math> such that for any other object <math>V</math> with arrows <math>A\rightarrow^{q_1} V\leftarrow^{q_2} B</math>, there is a unique arrow <math>A+B\to V</math> such that the diagram<br />
<br />
[[Image:A-Bdiagram.png]]<br />
<br />
commutes. The diagram <math>A \rightarrow^{i_1} A+B \leftarrow^{i_2} B</math> is called a ''coproduct cocone'', and the arrows are ''inclusion arrows''.<br />
<br />
For sets, we need to insist that instead of just any <math>S\times 0</math> and <math>T\times 1</math>, we need the specific construction taking pairs for the coproduct to work out well. The issue here is that the categorical product is not defined as one single construction, but rather from how it behaves with respect to the arrows involved. <br />
<br />
With this caveat, however, the coproduct in Set really is the disjoint union sketched above.<br />
<br />
For Hask, the coproduct is the type construction of <hask>Union</hask> above - more usually written <hask>Either a b</hask>.<br />
<br />
And following closely in the dualization of the things we did for products, there is a first <br />
<br />
'''Proposition''' If <math>C, C'</math> are both coproducts for some pair <math>A, B</math> in a category <math>D</math>, then they are isomorphic.<br />
<br />
The proof follows the exact pattern of the corresponding proposition for products.<br />
<br />
===Algebra of datatypes===<br />
<br />
Recall from [[User:Michiexile/MATH198/Lecture_3|Lecture 3]] that we can consider endofunctors as container datatypes.<br />
Some of the more obvious such container datatypes include:<br />
<haskell><br />
data 1 a = Empty<br />
data T a = T a<br />
</haskell><br />
These being the data type that has only one single element and the data type that has exactly one value contained.<br />
<br />
Using these, we can generate a whole slew of further datatypes. First off, we can generate a data type with any finite number of elements by <math>n = 1 + 1 + \dots + 1</math> (<math>n</math> times). Remember that the coproduct construction for data types allows us to know which summand of the coproduct a given part is in, so the single elements in all the <hask>1</hask>s in the definition of <hask>n</hask> here are all distinguishable, thus giving the final type the required number of elements.<br />
Of note among these is the data type <hask>Bool = 2</hask> - the Boolean data type, characterized by having exactly two elements.<br />
<br />
Furthermore, we can note that <math>1\times T = T</math>, with the isomorphism given by the maps<br />
<haskell><br />
f (Empty, T x) = T x<br />
g (T x) = (Empty, T x)<br />
</haskell><br />
<br />
Thus we have the capacity to ''add'' and ''multiply'' types with each other. We can verify, for any types <math>A,B,C</math><br />
<math>A\times(B+C) = A\times B + A\times C</math><br />
<br />
We can thus make sense of types like <math>T^3+2T^2</math> (either a triple of single values, or one out of two tagged pairs of single values).<br />
<br />
This allows us to start working out a calculus of data types with versatile expression power. We can produce recursive data type definitions by using equations to define data types, that then allow a direct translation back into Haskell data type definitions, such as:<br />
<br />
<math>List = 1 + T\times List</math><br />
<br />
<math>BinaryTree = T+T\times BinaryTree\times BinaryTree</math><br />
<br />
<math>TernaryTree = T+T\times TernaryTree\times TernaryTree\times TernaryTree</math><br />
<br />
<math>GenericTree = T1+T\times (List\circ GenericTree)</math><br />
<br />
The real power of this way of rewriting types comes in the recognition that we can use algebraic methods to reason about our data types. For instance:<br />
<br />
<haskell><br />
List = 1 + T * List <br />
= 1 + T * (1 + T * List) <br />
= 1 + T * 1 + T * T* List <br />
= 1 + T + T * T * List<br />
</haskell><br />
<br />
so a list is either empty, contains one element, or contains at least two elements. Using, though, ideas from the theory of power series, or from continued fractions, we can start analyzing the data types using steps on the way that seem completely bizarre, but arriving at important property. Again, an easy example for illustration:<br />
<br />
<haskell><br />
List = 1 + T * List -- and thus<br />
List - T * List = 1 -- even though (-) doesn't make sense for data types<br />
(1 - T) * List = 1 -- still ignoring that (-)...<br />
List = 1 / (1 - T) -- even though (/) doesn't make sense for data types<br />
= 1 + T + T*T + T*T*T + ... -- by the geometric series identity<br />
</haskell><br />
and hence, we can conclude - using formally algebraic steps in between - that a list by the given definition consists of either an empty list, a single value, a pair of values, three values, et.c.<br />
<br />
At this point, I'd recommend anyone interested in more perspectives on this approach to data types, and thinks one may do with them, to read the following references:<br />
<br />
====Blog posts and Wikipages====<br />
<br />
The ideas in this last section originate in a sequence of research papers from Conor McBride - however, these are research papers in logic, and thus come with all the quirks such research papers usually carry. Instead, the ideas have been described in several places by various blog authors from the Haskell community - which make for a more accessible but much less strict read.<br />
<br />
* http://en.wikibooks.org/wiki/Haskell/Zippers -- On zippers, and differentiating types<br />
* http://blog.lab49.com/archives/3011 -- On the polynomial data type calculus<br />
* http://blog.lab49.com/archives/3027 -- On differentiating types and zippers<br />
* http://comonad.com/reader/2008/generatingfunctorology/ -- Different recursive type constructions<br />
* http://strictlypositive.org/slicing-jpgs/ -- Lecture slides for similar themes.<br />
* http://blog.sigfpe.com/2009/09/finite-differences-of-types.html -- Finite differences of types - generalizing the differentiation approach.<br />
* http://homepage.mac.com/sigfpe/Computing/fold.html -- Develops the underlying theory for our algebra of datatypes in some detail.<br />
<br />
===Homework===<br />
<br />
Complete points for this homework consists of 4 out of 5 exercises. Partial credit is given.<br />
<br />
# What are the products in the category <math>C(P)</math> of a poset <math>P</math>? What are the coproducts?<br />
# Prove that any two coproducts are isomorphic.<br />
# Prove that any two exponentials are isomorphic.<br />
# Write down the type declaration for at least two of the example data types from the section of the algebra of datatypes, and write a <hask>Functor</hask> implementation for each.<br />
# * Read up on Zippers and on differentiating data structures. Find the derivative of List, as defined above. Prove that <math>\partial List = List \times List</math>. Find the derivatives of BinaryTree, and of GenericTree.</div>Jsnxhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=30077GHC/Type families2009-09-16T06:02:06Z<p>Jsnx: Seeming omission.</p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
<br />
== What are type families? ==<br />
<br />
Indexed type families, or type families for short, are type constructors that represent ''sets of types.'' Set members are denoted by supplying the type family constructor with type parameters, which are called ''type indices''. The difference between vanilla parametrised type constructors and family constructors is much like between parametrically polymorphic functions and (ad-hoc polymorphic) methods of type classes. Parametric polymorphic functions behave the same at all type instances, whereas class methods can change their behaviour in dependence on the class type parameters. Similarly, vanilla type constructors imply the same data representation for all type instances, but family constructors can have varying representation types for varying type indices.<br />
<br />
Indexed type families come in two flavours: ''data families'' and ''type synonym families''. They are the indexed family variants of algebraic data types and type synonyms, respectively. The instances of data families can be data types and newtypes.<br />
<br />
== Type families in GHC ==<br />
<br />
Indexed type families are a new GHC extension to facilitate type-level programming. Type families are a generalisation of [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types] and [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html associated type synonyms], and are described in a [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html recent ICFP paper]. They essentially provide type-indexed data types and named functions on types, which are useful for generic programming and highly parameterised library interfaces as well as interfaces with enhanced static information, much like dependent types. They might also be regarded as an alternative to functional dependencies, but provide a more functional style of type-level programming than the relational style of functional dependencies.<br />
<br />
== What do I need to use type families? ==<br />
<br />
The first stable release of GHC that properly supports type families is 6.10.1. (An early partial implementation was part of the 6.8 release, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundamental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Next, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and querying a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the latter can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> keyword. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is the first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implicitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This is for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change in correspondingly. An instance of the two-parameter class<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
become an instance of a single-parameter class, where the dependant type parameter turns into an associated type instance declaration:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1, Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
== Detailed definition of type synonym families ==<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the latter can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although it's overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of type families are very similar to standard type synonym declarations. The only two differences are that the keyword <hask>type</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>[e]</hask> instance for <hask>Elem</hask> becomes:<br />
<haskell><br />
instance (Eq (Elem [e])) => Collects ([e]) where<br />
type Elem [e] = e<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is <hask>[e]</hask>, which coincides with the only class parameter.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a type family used in a single program may only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two example to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] Manuel M. T. Chakravarty, Gabriele Keller, and Simon Peyton Jones. In ''Proceedings of The Tenth ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 241-253, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extension]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=QuickCheck_as_a_test_set_generator&diff=30069QuickCheck as a test set generator2009-09-15T03:22:19Z<p>Jsnx: Missing article.</p>
<hr />
<div><center><span style='font-size:xx-large; font-weight:bold'>Haskell as an ultimate "smoke testing" tool </span><p>OR</p> <p><span style='font-size:x-large; font-weight:bold'>Using QuickCheck as a DIY test data generator</span></p></center><br />
<br />
== Preface ==<br />
<br />
Recently, my wife approached me with the following problem: they had to<br />
test their re-implementation (in Java) of the part of the huge<br />
software system previously written in C++. The original system is poorly<br />
documented and only a small part of the sources were available.<br />
<br />
Among other things, they had to wrote a parser for home-brewn DSL<br />
designed to describe data structures. The DSL is a mix of ASN.1 and BNF<br />
grammars, describes a structure of some data records and simple<br />
business rules relevant to processing of said record. The DSL is not<br />
Turing-complete, but allows user to define it's own functions,<br />
specify math and boolean expression on fields and was designed as<br />
"ASN.1 on steroids".<br />
<br />
Problem is, that their implementation (in JavaCC) on this DSL parser<br />
was based on the single available description of the DSL grammar,<br />
which was presumably incomplete. They tested implementation on several<br />
examples available, but the question remained how to test the parser on a<br />
large subset of data in order to be fairly sure that "everything<br />
works"<br />
<br />
== The fame of Quick Check ==<br />
<br />
My wife observed me during the last (2005) ICFP contest and was amazed<br />
at the ease with which our team has tested our protocol parser and<br />
printer using Quick Check. So, she asked me whether it is possible to<br />
generate pseudo-random test data in the similar manner for use<br />
"outside" of Haskell?<br />
<br />
"Why not?" I thought. After all, I found it quite easy to generate<br />
instances of 'Arbitrary' for quite complex data structures.<br />
<br />
== Concept of the '''Variant''' ==<br />
<br />
The task was formulated as follows:<br />
<br />
* The task is to generate test datasets for the external program. Each dataset consists of several files, each containing 1 "record"<br />
<br />
* A "record" is essentially a Haskell data type<br />
<br />
* We must be able to generate pseudo-random "valid" and "invalid" data, to test that external program consumes all "valid" samples and fails to consume all "invalid" ones. Deviation from this behavior signifies an error in external program.<br />
<br />
Lets capture this notion of "valid" and "invalid" data in a type<br />
class:<br />
<br />
<haskell><br />
module Variant where<br />
<br />
import Control.Monad<br />
import Test.QuickCheck<br />
<br />
class Variant a where<br />
valid :: Gen a<br />
invalid :: Gen a<br />
</haskell> <br />
<br />
So, in order to make a set of test data of some type, the user must<br />
provide means to generate "valid" and "invalid" data of this type.<br />
<br />
If we can make a "valid" Foo (for suitable "data Foo = ...") and<br />
"invalid" Foo, then we should also be able to make a "random" Foo:<br />
<br />
<haskell><br />
instance Variant a => Arbitrary a where<br />
coarbitrary = undefined -- Not needed, Easily fixable<br />
arbitrary = oneof [valid, invalid]<br />
</haskell><br />
<br />
Thus, taking for example the following definition for our<br />
"data-to-test":<br />
<br />
<haskell><br />
data Record = InputRecord Name Number<br />
| OutputRecord Name Number OutputType deriving Show<br />
data Number = Number String deriving Show<br />
data Name = Name String deriving Show<br />
data OutputType = OutputType String deriving Show<br />
</haskell><br />
<br />
we could produce the following instances of the class "Variant":<br />
<br />
<haskell><br />
-- For definition of `neStringOf` see below, for now it is sufficient<br />
-- to say that `neStringOf first next` produces non-empty string whose<br />
-- first character is taken from `first` and all subsequent - from<br />
-- `next`<br />
garbledString = neStringOf ".,_+-" "abc0!@#$%^&*()."<br />
instance Variant Number where<br />
valid = liftM Number $ resize 4 $ neStringOf "123456789" "0123456789"<br />
invalid = liftM Number $ resize 4 $ garbledString<br />
instance Variant Name where<br />
valid = liftM Name $ elements [ "foo", "bar", "baz" ]<br />
invalid = liftM Name garbledString<br />
instance Variant OutputType where<br />
valid = liftM OutputType $ elements [ "Binary", "Ascii" ]<br />
invalid = liftM OutputType garbledString<br />
<br />
instance Variant Record where<br />
valid = oneof [ liftM2 InputRecord valid valid<br />
, liftM3 OutputRecord valid valid valid ]<br />
invalid = oneof [ liftM2 InputRecord valid invalid<br />
, liftM2 InputRecord invalid valid<br />
, liftM2 InputRecord invalid invalid<br />
, liftM3 OutputRecord invalid valid valid <br />
, liftM3 OutputRecord valid invalid valid <br />
, liftM3 OutputRecord valid valid invalid<br />
, liftM3 OutputRecord invalid invalid valid <br />
, liftM3 OutputRecord valid invalid invalid <br />
, liftM3 OutputRecord invalid valid invalid<br />
, liftM3 OutputRecord invalid invalid invalid<br />
]<br />
</haskell><br />
<br />
The careful reader will have already spotted that once we hand-coded the instances of 'Variant' for a few "basic" types (like 'Name', 'Number', 'OutputType' etc), defining instances of Variant for more complex datatypes becomes easy, though quite a tedious job. We call to the rescue a set of simple helpers to facilitate this task<br />
<br />
== Helper tools ==<br />
<br />
It could easily be seen that we consider an instance of a data type to be "invalid" if at least one of the arguments to the constructor is "invalid", whereas a "valid" instance should have all arguments to data type constructor to be "valid". This calls for some permutations:<br />
<br />
<haskell><br />
proper1 f = liftM f valid<br />
proper2 f = liftM2 f valid valid<br />
proper3 f = liftM3 f valid valid valid<br />
proper4 f = liftM4 f valid valid valid valid<br />
proper5 f = liftM5 f valid valid valid valid valid<br />
<br />
bad1 f = liftM f invalid<br />
bad2 f = oneof $ tail [ liftM2 f g1 g2 | g1<-[valid, invalid], g2<-[valid, invalid] ]<br />
bad3 f = oneof $ tail [ liftM3 f g1 g2 g3 | g1<-[valid, invalid], g2<-[valid, invalid], g3<-[valid, invalid] ]<br />
bad4 f = oneof $ tail [ liftM4 f g1 g2 g3 g4 | g1<-[valid, invalid], g2<-[valid, invalid], g3<-[valid, invalid], g4<-[valid, invalid] ]<br />
bad5 f = oneof $ tail [ liftM5 f g1 g2 g3 g4 g5 | g1<-[valid, invalid], g2<-[valid, invalid], g3<-[valid, invalid], g4<-[valid, invalid], g5<-[valid, invalid] ]<br />
</haskell><br />
<br />
With those helper definitions we could rewrite our Record instance as follows:<br />
<br />
<haskell><br />
instance Variant Record where<br />
valid = oneof [ proper2 InputRecord<br />
, proper3 OutputRecord ]<br />
invalid = oneof [ bad2 InputRecord<br />
, bad3 OutputRecord ]<br />
</haskell><br />
<br />
Note the drastic decrease in the size of the declaration!<br />
<br />
Oh, almost forgot to include the code for "neStringOf":<br />
<haskell><br />
neStringOf chars_start chars_rest =<br />
do s <- elements chars_start<br />
r <- listOf' $ elements chars_rest<br />
return (s:r)<br />
<br />
listOf' :: Gen a -> Gen [a]<br />
listOf' gen = sized $ \n -><br />
do k <- choose (0,n)<br />
vectorOf' k gen<br />
<br />
vectorOf' :: Int -> Gen a -> Gen [a]<br />
vectorOf' k gen = sequence [ gen | _ <- [1..k] ]<br />
</haskell><br />
<br />
== Producing test data ==<br />
<br />
OK, but how to use all those fancy declarations to actually produce some test data?<br />
<br />
Let's take a look at the following code:<br />
<br />
<haskell><br />
data DataDefinition = DataDefinition Name Record<br />
<br />
main = <br />
do let num = 200 -- Number of test cases in each dataset.<br />
let config = -- Describe several test datasets for "DataDefinition"<br />
-- by defining how we want each component of DataDefinition<br />
-- for each particular dataset - valid, invalid or random<br />
[ ("All_Valid", "txt", num, (valid, valid ))<br />
, ("Invalid_Name", "txt", num, (invalid, valid ))<br />
, ("Invalid_Record" , "txt" , num, (valid, invalid ))<br />
, ("Random", "txt", num, (arbitrary, arbitrary))<br />
]<br />
mapM_ create_test_set config<br />
<br />
create_test_set (fname, ext, count, gens) =<br />
do rnd <- newStdGen <br />
let test_set = generate 100 rnd $ vectorOf' count (mkDataDef gens)<br />
sequence_ $ zipWith (writeToFile fname ext) [1..] test_set <br />
where<br />
mkDataDef (gen_name, gen_rec) = liftM2 DataDefinition gen_name gen_rec<br />
<br />
writeToFile name_prefix suffix n x =<br />
do h <- openFile (name_prefix ++ "_" ++ pad n ++ "." ++ suffix) WriteMode <br />
hPutStrLn h $ show x<br />
hClose h <br />
where pad n = reverse $ take 4 $ (reverse $ show n) ++ (repeat '0')<br />
</haskell><br />
<br />
You see that we could control size, nature and destination of each test dataset. This approach was taken to produce test datasets for the task I described earlier. The final Haskell module had definitions for 40 Haskell datatypes, and the topmost datatype had a single constructor with 9 fields. <br />
<br />
This proved to be A Whole Lot Of Code(tm), and declaration of "instance Variant ..." proved to be a good 30% of total amount. Since most of them were variations of the "oneof [proper Foo, proper2 Bar, proper4 Baz]" theme, I started looking for a way so simplify/automate generation of such instances.<br />
<br />
== Deriving Variant instances automagically ==<br />
<br />
I took a a post made by Bulat Ziganshin on TemplateHaskell mailing list to show how to derive instances of 'Show' automatically, and hacked it to be able to derive instances of "Variant" in much the same way:<br />
<br />
<haskell><br />
import Language.Haskell.TH<br />
import Language.Haskell.TH.Syntax<br />
<br />
data T3 = T3 String<br />
<br />
deriveVariant t = do<br />
-- Get list of constructors for type t<br />
TyConI (DataD _ _ _ constructors _) <- reify t<br />
<br />
-- Make `valid` or `invalid` clause for one constructor:<br />
-- for "(A x1 x2)" makes "Variant.proper2 A"<br />
let mkClause f (NormalC name fields) = <br />
appE (varE (mkName ("Variant."++f++show(length fields)))) (conE name)<br />
<br />
-- Make body for functions `valid` and `invalid`:<br />
-- valid = oneof [ proper2 A | proper1 C]<br />
-- or<br />
-- valid = proper3 B, depending on the number of constructors<br />
validBody <- case constructors of<br />
[c] -> normalB [| $(mkClause "proper" c) |]<br />
cs -> normalB [| oneof $(listE (map (mkClause "proper") cs)) |]<br />
invalidBody <- case constructors of<br />
[c] -> normalB [| $(mkClause "bad" c) |]<br />
cs -> normalB [| oneof $(listE (map (mkClause "bad") cs)) |]<br />
<br />
-- Generate template instance declaration and replace type name (T1)<br />
-- and function body (x = "text") with our data<br />
d <- [d| instance Variant T3 where<br />
valid = liftM T3 valid<br />
invalid = liftM T3 invalid<br />
|]<br />
let [InstanceD [] (AppT showt (ConT _T3)) [ ValD validf _valid [], ValD invalidf _invalid [] ]] = d<br />
return [InstanceD [] (AppT showt (ConT t )) [ ValD validf validBody [], ValD invalidf invalidBody [] ]]<br />
<br />
-- Usage:<br />
$(deriveVariant ''Record)<br />
</haskell><br />
<br />
[[User:Adept|Adept]]<br />
<br />
[[Category:Idioms]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Tying_the_Knot&diff=29472Tying the Knot2009-08-08T22:41:02Z<p>Jsnx: Separated commentary from code.</p>
<hr />
<div>== Introduction ==<br />
<br />
This example illustrates different ways to define recursive data structures.<br />
To demonstrate the different techniques we show how to solve the same problem---writing an interpreter for a simple programming language---in three different ways. This is a nice example because, (i) it is interesting, (ii) the abstract syntax of the language contains mutually recursive structures, and (iii) the interpreter illustrates how to work with the recursive structures.<br />
<br />
(It would be useful to have some more text describing the examples.)<br />
<br />
== Download the files ==<br />
* [[Media:Interp1.lhs|Direct Recursion]]<br />
* [[Media:Interp2.lhs|Tying the Knot]]<br />
* [[Media:Interp3.lhs|Tying the Knot with GADTs]]<br />
<br />
== Other Examples ==<br />
<br />
* [http://twan.home.fmf.nl/blog/haskell/Knuth-Morris-Pratt-in-Haskell.details Knuth-Morris-Pratt algorithm for substring matching]<br />
<br />
== Migrated from the old wiki ==<br />
<br />
How to build a cyclic data structure.<br />
<br />
At first, the lack of pointer-updating operations in Haskell makes it seem that building cyclic structures (circular lists, graphs, etc) is impossible. This is not the case, thanks to the ability to define data using recursive equations. Here is a little trick called `tying the knot'.<br />
<br />
Remember that Haskell is a lazy language. A consequence of this is that while you are building the node, you can set the children to the final values straight away, even though you don't know them yet! It twists your brain a bit the first few times you do it, but it works fine.<br />
<br />
Here's an example. Say you want to build a circular, doubly-linked list, given a standard Haskell list as input. The back pointers are easy, but what about the forward ones?<br />
<haskell><br />
data DList a = DLNode (DList a) a (DList a)<br />
<br />
mkDList :: [a] -> DList a<br />
<br />
mkDList [] = error "must have at least one element"<br />
mkDList xs = let (first,last) = go last xs first<br />
in first<br />
<br />
where go :: DList a -> [a] -> DList a -> (DList a, DList a)<br />
go prev [] next = (next,prev)<br />
go prev (x:xs) next = let this = DLNode prev x rest<br />
(rest,last) = go this xs next<br />
in (this,last)<br />
<br />
takeF :: Integer -> DList a -> [a]<br />
takeF 0 _ = []<br />
takeF (n+1) (DLNode _ x next) = x : (takeF n next)<br />
<br />
takeR :: Show a => Integer -> DList a -> [a]<br />
takeR 0 _ = []<br />
takeR (n+1) (DLNode prev x _) = x : (takeR n prev)<br />
</haskell><br />
(takeF and takeR are simply to let you look at the results of mkDList: they take a specified number of elements, either forward or backward).<br />
<br />
The trickery takes place in `go'. `go' builds a segment of the list, given a pointer to the node off to the left of the segment and off to the right. Look at the second case of `go'. We build the first node of the segment, using the given prev pointer for the left link, and the node pointer we are *about* to compute in the next step for the right link.<br />
<br />
This goes on right the way through the segment. But how do we manage to create a *circular* list this way? How can we know right at the beginning what the pointer to the end of the list will be?<br />
<br />
Take a look at mkDList. Here, we simply take the (first,last) pointers we get from `go', and *pass them back in* as the next and prev pointers respectively, thus tying the knot. This all works because of lazy evaluation.<br />
<br />
Somehow the following seems more straightforward to me, though perhaps I'm missing the point here:<br />
<haskell><br />
data DList a = DLNode (DList a) a (DList a)<br />
<br />
rot :: Integer -> [a] -> [a]<br />
rot n xs | n < 0 = rot (n+1) ((last xs):(init xs))<br />
| n == 0 = xs<br />
| n > 0 = rot (n-1) (tail xs ++ [head xs])<br />
<br />
mkDList :: [a] -> DList a<br />
mkDList [] = error "Must have at least one element."<br />
mkDList xs = DLNode (mkDList $ rot (-1) xs) (head xs) (mkDList $ rot 1 xs)<br />
</haskell><br />
<br />
- CaleGibbard<br />
<br />
The problem with this is it won't make a truly cyclic data structure, rather it will constantly be generating the rest of the list. To see this use trace (in Debug.Trace for GHC) in mkDList (e.g. mkDList xs = trace "mkDList" $ ...) and then takeF 10 (mkDList "a"). Add a trace to mkDList or go or wherever you like in the other version and note the difference.<br />
<br />
-- DerekElkins<br />
<br />
Yeah, thanks, I see what you mean.<br />
<br />
This is so amazing that everybody should have seen it, so here's the trace. I put trace "\n--go{1/2}--" $ directly after the two go definitions:<br />
<br />
<haskell><br />
*Main> takeF 10 $ mkDList [1..3]<br />
<br />
--go2--<br />
[1<br />
--go2--<br />
,2<br />
--go2--<br />
,3<br />
--go1--<br />
,1,2,3,1,2,3,1]<br />
<br />
</haskell><br />
<br />
- CaleGibbard<br />
<br />
The above works for simple cases, but sometimes you need construct some very complex data structures, where the pattern of recursion is not known at compile time. If this is the case, may need to use an auxiliary dictionary data structure to help you tie your knots.<br />
<br />
Consider, for example, how you would implement deterministic finite automata (DFAs). One possibility is:<br />
<haskell><br />
type IndirectDfa a = (Int, [IndirectState a])<br />
<br />
data IndirectState a =<br />
IndirectState Bool [(a, Int)]<br />
</haskell><br />
That is, a DFA is a set of states, one of which is distinguished as being the "start state". Each state has a number of transitions which lead to other states, as well as a flag which specifies or not the state is final.<br />
<br />
This representation is fine for manipulation, but it's not as suitable for actually executing the DFA as it could be because we need to "look up" a state every time we make a transition. There are relatively cheap ways to implement this indirection, of course, but ideally we shouldn't have to pay much for it.<br />
<br />
What we really want is a recursive data structure:<br />
<br />
<haskell><br />
data DirectDfa a<br />
= DirectState Bool [(a, DirectDfa a)]<br />
</haskell><br />
Then we can just execute the DFA like this:<br />
<haskell><br />
runDfa :: (Eq a) => DirectDfa a -> [a] -> Bool<br />
runDfa (DirectState final trans) []<br />
= final<br />
runDfa (DirectState final trans) (x:xs)<br />
= case [ s | (x',s) <- trans, x == x' ] of<br />
[] -> False<br />
(s:_) -> runDfa s xs<br />
</haskell><br />
(Note: We're only optimising state lookup here, not deciding which transition to take. As an exercise, consider how you might optimise transitions. You may wish to use [[RunTimeCompilation]].)<br />
<br />
Turning the indirect recursion into direct recursion requires tying knots, and it's not immediately obvious how to do this by holding onto lazy pointers, because any state can potentially point to any other state (or, indeed, every other state).<br />
<br />
What we can do is introduce a dictionary data structure to hold the (lazily evaluated) new states, then introducing a recursive reference can be done with a a simple dictionary lookup. In principle, you could use any dictionary data structure (e.g. Map). However, in this case, the state numbers are dense integers, so it's probably easiest to use an array:<br />
<haskell><br />
indirectToDirect :: IndirectDfa a -> DirectDfa a<br />
indirectToDirect (start, states)<br />
= tieArray ! start<br />
where<br />
tieArray = array (0,length states - 1)<br />
[ (i,direct s) | (i,s) <- zip [0..] states ]<br />
<br />
direct (IndirectState final trans)<br />
= DirectState final [ (x, tieArray ! s) | (x,s) <- trans ]<br />
</haskell><br />
Note how similar this is to the technique of [[MemoisingCafs]]. In fact what we've done here is "memoised" the data structure, using something like [[HashConsing]].<br />
<br />
As noted previously, pretty much any dictionary data structure will do. Often you can even use structures with slow lookup (e.g. association lists). This is because fully lazy evaluation ensures that you only pay for each lookup the first time you use it; subsequent uses of the same part of the data structure are effectively free.<br />
<br />
-- AndrewBromage<br />
<br />
Transformations of cyclic graphs and the Credit Card Transform<br />
<br />
Cycles certainly make it difficult to transform graphs in a pure non-strict language. Cycles in a source graph require us to devise a way to mark traversed nodes -- however we cannot mutate nodes and cannot even compare nodes with a generic ('derived') equality operator. Cycles in a destination graph require us to keep track of the already constructed nodes so we can complete a cycle. An obvious solution is to use a state monad and IORefs. There is also a monad-less solution, which is less obvious: seemingly we cannot add a node to the dictionary of already constructed nodes until we have built the node. This fact means that we cannot use the updated dictionary when building the descendants of the node -- which need the updated dictionary to link back. The problem can be overcome however with a ''credit card transform'' (a.k.a. "buy now, pay later" transform). To avoid hitting the bottom, we just have to "pay" by the "due date".<br />
<br />
For illustration, we will consider the problem of printing out a non-deterministic finite automaton (NFA) and transforming it into a deterministic finite automaton (DFA). Both NFA and DFA are represented as cyclic graphs. The problem has been discussed on the Haskell/Haskell-Cafe mailing lists. The automata in question were to recognize strings over a binary alphabet.<br />
<br />
A state of an automaton over a binary alphabet is a data structure:<br />
<haskell><br />
data (Ord l,Show l) => FaState l =<br />
FaState {label :: l, acceptQ :: Bool,<br />
trans0:: [FaState l],<br />
trans1:: [FaState l]}<br />
</haskell><br />
whose fields have the obvious meaning. Label is used for printing out and comparing states. The flag acceptQ tells if the state is final. Since an FaState can generally represent a non-deterministic automaton, transitions are the ''lists'' of states.<br />
<br />
An automaton is then a list of starting states.<br />
<haskell><br />
type FinAu l = [FaState l]<br />
</haskell><br />
For example, an automaton equivalent to the regular expression "0*(0(0+1)*)*" could be defined as:<br />
<haskell><br />
dom18 = [one]<br />
where one = FaState 1 True [one,two] []<br />
two = FaState 2 True [two,one] [one,two]<br />
</haskell><br />
using the straightforward translation from a regular expression to an NFA.<br />
<br />
We would like to compare and print automata and their states:<br />
<haskell><br />
instance (Ord l,Show l) => Eq (FaState l) where<br />
(FaState l1 _ _ _) == (FaState l2 _ _ _) = l1 == l2<br />
</haskell><br />
<br />
Printing a FaState however poses a slight problem. For example, the state labeled '1' in the automaton dom18 refers to itself. If we blindly 'follow the links', we will loop forever. Therefore, we must keep track of the already printed states. We need a data structure for such an occurrence check, with the following obvious operations:<br />
<br />
<haskell><br />
class OCC occ where<br />
empty:: occ a<br />
seenp:: (Eq a) => a -> occ a -> Bool -- occurrence check predicate<br />
put:: a -> occ a -> occ a -- add an item<br />
</haskell><br />
<br />
In this article, we realize such a data structure as a list. In the future, we can pull in something fancier from the Edison collection:<br />
<br />
<haskell><br />
instance OCC [] where<br />
empty = []<br />
seenp = elem<br />
put = (:)<br />
</haskell><br />
<br />
We are now ready to print an automaton. To be more precise, we traverse the corresponding graph depth-first, pre-order, and keep track of the already printed states. A 'states_seen' datum accumulates the shown states, so we can be sure we print each state only once and thus avoid the looping.<br />
<br />
<haskell><br />
instance (Ord l,Show l) => Show (FaState l) where<br />
show state = "{@" ++ showstates [state] (empty::[FaState l]) "@}"<br />
where<br />
-- showstates worklist seen_states suffix<br />
showstates [] states_seen suffix = suffix<br />
showstates (st:rest) states_seen suffix<br />
| st `seenp` states_seen = showstates rest states_seen suffix<br />
showstates (st@(FaState l accept t0 t1):rest) states_seen suffix =<br />
showstate st<br />
$ showstates (t0++t1++rest) (st `put` states_seen) suffix<br />
<br />
showstate (FaState l accept t0 t1) suffix<br />
= "{State " ++ (show l) ++<br />
" " ++ (show accept) ++ " " ++ (show $ map label t0) ++<br />
" " ++ (show $ map label t1) ++ "}" ++ suffix<br />
</haskell><br />
<br />
Now,<br />
<br />
<haskell><br />
CCardFA> print dom18 -- prints as<br />
CCardFA> [{@{State 1 True [1,2] []}{State 2 True [2,1] [1,2]}@}]<br />
</haskell><br />
<br />
The acceptance function for our automata can be written as follows. The function takes the list of starting states and the string over the boolean alphabet. The function returns True if the string is accepted.<br />
<br />
<haskell><br />
finAuAcceptStringQ start_states str =<br />
foldr (\l seed -> acceptP l str || seed) False start_states<br />
where acceptP (FaState _ acceptQ _ _) [] = acceptQ<br />
acceptP (FaState _ _ t0 t1) (s:rest) =<br />
finAuAcceptStringQ (if s then t1 else t0) rest<br />
</haskell><br />
<br />
To test the automata, we can try<br />
<br />
<haskell><br />
test1= finAuAcceptStringQ dom18 $ map (>0) [0,1,0,1]<br />
test2= finAuAcceptStringQ dom18 $ map (>0) [1,1,0,1]<br />
test3= finAuAcceptStringQ dom18 [True]<br />
test4= finAuAcceptStringQ dom18 [False]<br />
</haskell><br />
<br />
We are now ready to write the NFA->DFA conversion, a determinization of an NFA. We implement the textbook algorithm of tracing set of NFA states. A state in the resulting DFA corresponds to a list of the NFA states. A DFA is generally a cyclic graph, often with cycles of length 1 (self-referenced nodes). To be able to "link back" as we build DFA states, we have to remember the already constructed states. We need a data structure, a dictionary of states:<br />
<br />
<haskell><br />
class StateDict sd where<br />
emptyd :: sd (l,FaState l)<br />
locate :: (Eq l) => l -> sd (l,FaState l) -> Maybe (FaState l)<br />
putd :: (l,FaState l) -> sd (l,FaState l) -> sd (l,FaState l)<br />
</haskell><br />
<br />
For now, we realize this dictionary as an associative list. If performance matters, we can use a fancier dictionary from the Edison<br />
<br />
<haskell><br />
instance StateDict [] where<br />
emptyd = []<br />
locate = lookup<br />
putd = (:)<br />
</haskell><br />
<br />
The work of the NFA->DFA conversion is done by the following function determinize_cc. The function takes a list of NFA states, the dictionary of the already built states, and returns a pair <hask>([dfa_state], updated_dictionary)</hask> where <hask>[dfa_state]</hask> is a singleton list.<br />
<br />
<haskell><br />
-- [nfa_state] -> dictionary_of_seen_states -><br />
-- ([dfa_state],updated_dictionary)<br />
-- [dfa_state] is a singleton list<br />
determinize_cc states converted_states =<br />
-- first, check the cache to see if the state has been built already<br />
case dfa_label `locate` converted_states of<br />
Nothing -> build_state<br />
Just dfa_state -> ([dfa_state],converted_states)<br />
where<br />
-- [NFA_labels] -> DFA_labels<br />
det_labels = sort . nub . (map label)<br />
dfa_label = det_labels states<br />
<br />
-- find out NFA-followers for [nfa_state] upon ingestion of 0 and 1<br />
(t0_followers,t1_followers) =<br />
foldr (\st (f0,f1) -> (trans0 st ++ f0, trans1 st ++ f1))<br />
([],[]) states<br />
acceptQ' = or (map acceptQ states)<br />
<br />
-- really build the dfa state and return ([dfa_state],updated_cache)<br />
build_state = let<br />
-- note, the dfa_state is computed _below_<br />
converted_states1 = (dfa_label,dfa_state) `putd` converted_states<br />
(t0', converted_states2) =<br />
(determinize_cc t0_followers converted_states1)<br />
(t1', converted_states3) =<br />
(determinize_cc t1_followers converted_states2)<br />
dfa_state =<br />
(FaState dfa_label acceptQ' t0' t1')<br />
in ([dfa_state],converted_states3)<br />
</haskell><br />
The front end of the NFA->DFA transformer:<br />
<hask>finAuDeterminize states = fst $ determinize_cc states []</hask><br />
<br />
At the heart of the credit card transform is the phrase from the above code:<br />
<hask> converted_states1 = (dfa_label,dfa_state) `putd` converted_states</hask><br />
<br />
The phrase expresses the addition to the dictionary of the 'converted_states' of a 'dfa_state' that we haven't built yet. The computation of the 'dfa_state' is written 4 lines below the phrase in question. Because (,) is non-strict in its arguments and locate is non-strict in its result, we can get away with a mere promise to "pay". Note that the computation of the dfa_state needs t0' and t1', which in turn rely on 'converted_states1'. This fact shows that we can tie the knot by making a promise to compute a state, add this promise to the dictionary of the built states, and use the updated dictionary to build the descendants. Because Haskell is a non-strict language, we don't need to do anything special to make the promise. Every computation is Haskell is by default a promise.<br />
<br />
We can print the DFA for dom18 to see what we've got:<br />
<haskell><br />
CCardFA> finAuDeterminize dom18<br />
CCardFA>-- which shows<br />
CCardFA> [{@{State [1] True [[1,2]] [[]] }<br />
CCardFA> {State [1,2] True [[1,2]] [[1,2]]}<br />
CCardFA> {State [] False [[]] [[]] }@}]<br />
</haskell><br />
which is indeed a DFA (which happens to be minimal) recognizing (0+1)* - 1(0+1)*<br />
<br />
We can run the determinized FA using the same function finAuAcceptStringQ:<br />
<haskell><br />
test1' = finAuAcceptStringQ (finAuDeterminize dom18) $ map (>0) [0,1,0,1]<br />
test2' = finAuAcceptStringQ (finAuDeterminize dom18) $ map (>0) [1,1,0,1]<br />
</haskell><br />
<br />
The complete code for this example is in http://pobox.com/~oleg/ftp/Haskell/CCard-transform-DFA.lhs. Another example of tying a knot in the case of forward links, by using a fixed-point combinator, is discussed in http://www.mail-archive.com/haskell@haskell.org/msg10687.html.<br />
<br />
-- Oleg<br />
<br />
For a long time, I've had an issue with Oleg's reply to Hal Daume III, the "forward links" example. The problem is that it doesn't really exploit laziness or circular values. It's solution would work even in a strict language. It's simply a functional version of the standard approach: build the result with markers and patch it up afterwards. It is a fairly clever way of doing purely something that is typically done with references and mutable update, but it doesn't really address what Hal Daume III was after. Fixing Hal Daume's example so that it won't loop is relatively trivial; simply change the case to a let or equivalently use a lazy pattern match in the case. However, if that's all there was to it, I would've written this a long time ago.<br />
<br />
The problem is that it no longer gives you control of the error message or anyway to recover from it. With GHC's extensions to exception handling you could do it, but you'd have to put readDecisionTree in the IO monad to recover from it, and if you wanted better messages you'd have to put most of the parsing in the IO monad so that you could catch the error earlier and provide more information then rethrow. What's kept me is that I couldn't figure out a way to tie the knot when the environment had a type like, Either String [(String,DecisionTree)]. This is because it's impossible for this case; we decide whether to return Left "could not find subtree" or Right someValue and therefore whether the environment is Left or Right based on whether we could find the subtree in the environment. In effect, we need to lookup a value in an environment we may return to know whether to return it. Obviously this is a truly circular dependency. This made me think that Oleg's solution was as good as any other and better than some (actually, ironically Oleg's solution also uses a let instead of a case, however, there's nothing stopping it from being a case, but it still would provide no way to recover from it without effectively doing what is mentioned below). Recently, I've thought about this again and the solution is obvious and follows directly from the original definition modified to use let. It doesn't loop because only particular values in the lookup table fail, in fact, you might never know there was a variable lookup error if you didn't touch all of the tree. This translates directly into the environment having type [(String,Either String DecisionTree)]. There are several benefits to this approach compared to Oleg's: 1) it solves my original problem, you are now able to specify the error messages (Oleg's can do this), 2) it goes beyond that (and beyond Hal Daume's original "specification") and also allows you to recover from an error without resorting to the IO monad and/or extensions (Oleg's can't do this), 3) it does implicitly what Oleg's version does explicitly, 4) because of (3) it shares properly while Oleg's does not*, 5) both the environment and the returned value are made up of showable values, not opaque functions, 6) it requires less changes to the original code and is more localized than Oleg's solution; only the variable lookup and top-level function will need to change.<br />
<br />
To recover, all one needs to do is make sure all the values in the lookup table are Right values. If they aren't, there are various ways you could collect the information; there are also variations on how to combine error information and what to provide. Even without a correctness check, you can still provide better error messages for the erroneous thunks. A possible variation that loses some of the benefits, is to change the DecisionTree type (or have a different version, [[IndirectComposite]] comes to mind here) that has Either ErrorInfo ErrorDecisionTree subnodes, which will allow you to recover at any time (though, if you want to make a normal DecisionTree out of it you will lose sharing). Also, the circular dependency only comes up if you need to use the environment to decide on an error. For example, a plain old syntactic parse error can cyclicly use an Either ErrorInfo [(String,DecisionTree)] perfectly fine (pass in fromRight env where fromRight ~(Right x) = x). It will also work even with the above approach giving the environment the type Either [(String,Either ErrorInfo DecisionTree)]. Below is code for a simplified scenario that does most of these things,<br />
<br />
<haskell><br />
module Main where<br />
import Maybe ( fromJust )<br />
import Monad<br />
<br />
main :: IO ()<br />
main = do<br />
input <- getContents<br />
length input `seq` print (fixup input)<br />
<br />
instance Monad (Either s) where<br />
return = Right<br />
m >>= f = either Left f m<br />
<br />
isLeft :: Either a b -> Bool<br />
isLeft (Left _) = True<br />
isLeft _ = False<br />
<br />
fromRight :: Either a b -> b<br />
fromRight ~(Right x) = x<br />
<br />
fixup :: String -> Either String [(String,Either String String)]<br />
fixup input = env<br />
where env = mapM (parse (fromRight env) . words) (lines input)<br />
<br />
checkedFixup :: String -> Either String [(String,String)]<br />
checkedFixup input =<br />
case fixup input of<br />
Left err -> Left err<br />
Right env -> case filter (isLeft . snd) env of<br />
[] -> Right $ map (\(n,Right v) -> (n,v)) env<br />
(_,Left err):_ -> Left err<br />
<br />
parse :: [(String,Either String String)] -> [String] -> Either String (String,Either String String)<br />
parse env ("define":name:values) = Right (name,values')<br />
where values' = liftM unwords $ mapM lookupRef values<br />
lookupRef ('*':word)<br />
= maybe (Left $ "couldn't find "++word++" in "++name)<br />
id<br />
(lookup word env)<br />
lookupRef word = Right word<br />
parse env input = Left $ "parse error with: "++unwords input<br />
</haskell><br />
checkedFixup demonstrates how you could check and recover, but since the environment is the return value neither fixup or checkedFixup quite illustrate having potentially erroneous thunks in the actual return value. Some example input,<br />
<haskell><br />
define x *y *y<br />
define y a b<br />
outputs Right [("x",Right "a b a b"),("y",Right "a b")]<br />
define x *y *y<br />
aousht<br />
define y a b<br />
outputs Left "parse error with: aousht"<br />
define x *y *z<br />
define y a b<br />
define z *w<br />
outputs Right [("x",Left "couldn't find w in z"),("y",Right "a b"),("z",Left "couldn't find w in z")]<br />
</haskell><br />
<br />
* Consider a tree Y that contains the subtree X twice. With Oleg's version, when we resolve the "X" variable we look up a (manually) delayed tree and then build X. Each subtree of Y will build it's own version of X. With the truly circular version each subtree of Y will be the same, possibly erroneous, thunk that builds X, if the thunk isn't erroneous then when it is updated both of Y's subtrees will point to the same X.<br />
<br />
-- DerekElkins<br />
<br />
== See also ==<br />
http://haskell.org/wikisnapshot/TyingTheKnot.html<br />
<br />
[[Category:Code]]<br />
[[Category:Idioms]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=The_Monad.Reader/Issue4/Why_Attribute_Grammars_Matter&diff=28404The Monad.Reader/Issue4/Why Attribute Grammars Matter2009-05-30T04:11:20Z<p>Jsnx: Sentence seems to have been clipped.</p>
<hr />
<div>=Why Attribute Grammars Matter=<br />
:''by Wouter Swierstra for The Monad.Reader Issue Four''; 01-07-05<br />
<br />
==Introduction==<br />
Almost twenty years have passed since John Hughes influential paper [http://www.math.chalmers.se/~rjmh/Papers/whyfp.html Why Functional Programming Matters]. At the same time the first work on<br />
attribute grammars and their relation to functional programming<br />
appeared. Despite the growing popularity of functional programming,<br />
attribute grammars remain remarkably less renown.<br />
<br />
The purpose of this article is twofold. On the one hand it illustrates how<br />
functional programming sometimes scales poorly and how<br />
attribute grammars can remedy these problems. On the other hand it aims to<br />
provide a gentle introduction to attribute grammars for seasoned functional<br />
programmers.<br />
<br />
==The problem==<br />
John Hughes argues that with the increasing complexity of modern<br />
software systems, modularity has become of paramount importance to software<br />
development. Functional languages provide new kinds of ''glue'' that create<br />
new opportunities for more modular code. In particular, Hughes stresses<br />
the importance of higher-order functions and lazy evaluation. There are<br />
plenty of examples where this works nicely - yet situations arise where<br />
the glue that functional programming provides somehow isn't quite enough.<br />
<br />
Perhaps a small example is in order. Suppose we want to write a function<br />
<tt>diff :: [Float] -> [Float]</tt> that given a list <tt>xs</tt>, calculates a new list where every element <tt>x</tt> is replaced with the difference between <tt>x</tt> and the<br />
average of <tt>xs</tt>. Similar problems pop up in any library for performing<br />
statistical calculations.<br />
<br />
===Higher-order functions===<br />
Let's tackle the problem with some of Haskell's most powerful glue - higher-order functions. Any beginning Haskell programmer should be able to concoct the solution presented in Listing One. The average is computed using functions from the Prelude. The obvious function using this average is then mapped over the original list. So far, so good.<br />
<br />
<haskell><br />
--- Listing One ---<br />
<br />
diff :: [Float] -> [Float]<br />
diff xs = map (\x -> x - (avg xs)) xs<br />
<br />
avg :: [Float] -> Float<br />
avg xs = sum xs / genericLength xs<br />
</haskell><br />
<br />
There are, however, a few things swept under the rug in this example. First<br />
of all, this simple problem requires three traversals of the original<br />
list. Computing additional values from the original list will require even<br />
more traversals.<br />
<br />
Secondly, the solution is so concise because it depends on Prelude<br />
functions. If the values were stored in a slightly different data structure,<br />
the solution would require a lot of tedious work. We could, of course,<br />
define our own higher-order functions, such as <tt>map</tt> and <tt>fold</tt>, or even<br />
resort to generic programming. There are, however,<br />
more ways to skin this particular cat.<br />
<br />
This problem illustrates the sheer elegance of functional programming. We<br />
do pay a price for the succinctness of the solution. Multiple traversals<br />
and boilerplate code can both be quite a head-ache. If we want to perform<br />
complex computations over custom data structures, we may want to consider an<br />
alternative approach.<br />
<br />
Fortunately, as experienced functional programmers, we have another card up<br />
our sleeve.<br />
<br />
===Lazy evaluation===<br />
The second kind of glue that functional programming provides is lazy<br />
evaluation. In essence, lazy evaluation only evaluates expressions when<br />
they become absolutely necessary.<br />
<br />
In particular, lazy evaluation enables the definition of ''circular programs'' that bear a dangerous resemblance to undefined values. Circular<br />
programs tuple separate computations, relying on lazy evaluation to feed<br />
the results of one computation to another.<br />
<br />
In our example, we could simply compute the length and sum of the list at<br />
the same time:<br />
<br />
<haskell><br />
average :: [Float] -> Float<br />
average xs = let<br />
nil = (0.0, 0.0)<br />
cons x (s,l) = (x + s, 1.0 + l)<br />
(sum,length) = foldr cons nil xs<br />
in sum / length<br />
</haskell><br />
<br />
We can eliminate traversals by tupling computations! Can we compute the<br />
resulting list at the same time as computing the sum and length? Let's try:<br />
<br />
<haskell><br />
diff :: [Float] -> [Float]<br />
diff xs = let<br />
nil = (0.0, 0.0, [])<br />
cons x (s,l,rs) = (x+s, 1.0+l, (x - ....) : rs)<br />
(sum,length,res) = foldr cons nil xs<br />
in res<br />
</haskell><br />
<br />
We run into trouble when we try to use the average to construct the<br />
resulting list. The problem is, that we haven't computed the average, but<br />
somehow want to use it during the traversal. To solve this, we don't actually<br />
compute the resulting list, but rather compute a function taking the<br />
average to the resulting list:<br />
<br />
<haskell><br />
diff :: [Float] -> [Float]<br />
diff xs =<br />
let<br />
nil = (0.0, 0.0, \avg -> [])<br />
cons x (s,l,rs) = (x+s, 1.0+l, \avg -> (x - avg) : rs avg)<br />
(sum,length,res) = foldr cons nil xs<br />
in<br />
res (sum / length)<br />
</haskell><br />
<br />
We can generalize this idea a bit further. Suppose that we want to compute<br />
other values that use the average. We could just add an <tt>avg</tt> argument to<br />
every element of the tuple that needs the average. It is a bit nicer,<br />
however, to lift the <tt>avg</tt> argument outside the tuple. Our final listing<br />
now becomes:<br />
<br />
<haskell><br />
--- Listing Two ---<br />
<br />
diff :: [Float] -> [Float]<br />
diff xs =<br />
let<br />
nil avg = (0.0, 0.0, [])<br />
cons x fs avg =<br />
let<br />
(s,l,ds) = fs avg<br />
in<br />
(s+x,l+1.0,x-avg : ds)<br />
(sum,length,ds) = foldr cons nil xs (sum / length)<br />
in<br />
ds<br />
</haskell><br />
<br />
Now every element of the tuple can refer to the average, rather than just<br />
the final list.<br />
<br />
This ''credit card transformation'' eliminates multiple traversals by<br />
tupling computations. We use the average without worrying if we have<br />
actually managed to compute it. When we actually write the fold, however,<br />
we have to put our average where our mouth is. Fortunately, the <tt>sum</tt> and<br />
<tt>length</tt> don't depend on the average, so we are free to use these values to<br />
tie the recursive knot.<br />
<br />
The code in Listing Two only needs a single traversal and one<br />
higher-order function. It apparently solves the problems with the code in<br />
Listing One.<br />
<br />
Hold on a minute. What ever happened to the elegance of our previous<br />
solution? Our second solution appears to have sacrificed clarity for the<br />
sake of efficiency. Who in their right minds would want to write the code<br />
in Listing Two? I wouldn't. Maybe, just maybe, we can do a bit better.<br />
<br />
==Attribute Grammars==<br />
Before even explaining what an attribute grammar is, think back to when you<br />
first learned about ''folds''. Initially, a fold seems like a silly<br />
abstraction. Why should I bother writing simple functions as folds? After<br />
all, I already know how to write the straightforward solution. It's only<br />
after a great deal of experience with functional programming that you learn<br />
to recognize folds as actually being a worthwhile abstraction. Learning<br />
about attribute grammars is similar in more ways than one.<br />
<br />
So what are attribute grammars? I'll have a bit more to say about that<br />
later. For now, let's see what the attribute grammar solution to our<br />
running example looks like.<br />
<br />
===The attribute grammar solution===<br />
I'll introduce attribute grammars using the syntax of the [http://www.cs.uu.nl/wiki/Center/AttributeGrammarSystem Utrecht University Attribute Grammar] system or UUAG for short. The UUAG system takes a file<br />
containing an attribute grammar definition and generates a Haskell module<br />
containing ''semantic functions'', determined by the attribute grammar. The<br />
attribute grammar determines a computation over some data structure; the<br />
semantic functions correspond to the actual Haskell functions that perform<br />
the computation.<br />
<br />
Although the UUAG system's syntax closely resembles Haskell, it is<br />
important to realize that the UUAG system is a Haskell pre-processor and<br />
not a complete Haskell compiler.<br />
<br />
So what does an attribute grammar file look like? Well, first of all we<br />
have to declare the data structure we're working with. In our example, we<br />
simply have a list of Floats.<br />
<br />
<haskell><br />
--- Listing Three ---<br />
<br />
DATA Root<br />
| Root list : List<br />
DATA List<br />
| Nil<br />
| Cons head : Float tail : List<br />
</haskell><br />
<br />
Datatypes are declared with the keyword <tt>DATA</tt>, followed by a list of<br />
constructors. Every node explicitly gives the name and type of all its<br />
children. In our example we have an empty list <tt>Nil</tt> and a list constructor<br />
<tt>Cons</tt> with two children, <tt>head</tt> and <tt>tail</tt>. For reasons that will become<br />
apparent later on, we add an additional datatype corresponding to the root<br />
of our list.<br />
<br />
So now that we've declared our datatype, let's add some ''attributes''. If we<br />
want to compute the average element, we'll need the length of the<br />
list. Listing Four contains introduces our first attribute corresponding to<br />
a list's length.<br />
<br />
<haskell><br />
--- Listing Four ---<br />
<br />
ATTR List [|| length : Float]<br />
SEM List<br />
| Nil lhs.length = 0.0<br />
| Cons lhs.length = 1.0 + @tail.length<br />
</haskell><br />
<br />
Let's go over the code line by line.<br />
<br />
An attribute has to be declared before it can actually be defined. An<br />
attribute is declared using the <tt>ATTR</tt> statement. This example declares a<br />
single ''synthesized'' attribute called <tt>length</tt> of type <tt>Float</tt>. A<br />
synthesized attribute is typically a value you are trying to compute bottom<br />
up. Synthesized attributes are declared to the right of the second<br />
vertical bar. We'll see other kinds attributes shortly.<br />
<br />
Now that we've declared our first attribute, we can actually define it. A<br />
<tt>SEM</tt> statement begins by declaring for which data type attributes are<br />
being defined. In our example we want to define an attribute on a <tt>List</tt>,<br />
hence we write <tt>SEM List</tt>. We can subsequently give attribute definitions<br />
for the constructors of our <tt>List</tt> data type.<br />
<br />
Every attribute definition consists of several parts. We begin by<br />
mentioning the constructor for which we define an attribute. In our example<br />
we give two definitions, one for <tt>Nil</tt> and one for <tt>Cons</tt>.<br />
<br />
The second part of the attribute definition describes which attribute is<br />
being defined. In our example we define the attribute <tt>length</tt> for the<br />
''left-hand side'', or <tt>lhs</tt>. A lot of the terminology associated with<br />
attribute grammars comes from the world of context-free grammars. As this<br />
tutorial focuses on functional programmers, rather than formal language<br />
gurus, feel free to read <tt>lhs</tt> as "parent node". It seems a bit odd to<br />
write <tt>lhs.length</tt> explicitly, but we'll see later on why merely writing<br />
<tt>length</tt> doesn't suffice.<br />
<br />
Basically, all we've only said that the two definitions define the <tt>length</tt><br />
of <tt>Nil</tt> and <tt>Cons</tt>. We still have to fill in the necessary definition. The<br />
actual definition of the attributes takes place to the right of the equals<br />
sign. Programmers are free to write any valid Haskell expression. In fact,<br />
the UUAG system does not analyse the attribute definitions at all, but merely<br />
copies them straight into the resulting Haskell module. In our example, we<br />
want the length of the empty list to be <tt>0.0</tt>. The case for <tt>Cons</tt> is a bit<br />
trickier.<br />
<br />
In the <tt>Cons</tt> case we want to be increment the length computed so far. To<br />
do so we need to be able to refer to other attributes. In particular we<br />
want to refer to the <tt>length</tt> attribute of the tail. The expression<br />
<tt>@tail.length</tt> does just that. In general, you're free to refer to any<br />
synthesized attribute ''attr'' of a child node ''c'' by writing <tt>@c.attr</tt>.<br />
<br />
The <tt>length</tt> attribute can be depicted pictorally as follows:<br />
<br />
[[Image:WAGM-Avg.png|The length attribute]]<br />
<br />
'''Exercise:''' Declare and define a synthesized attribute <tt>sum</tt> that<br />
computes the sum of a <tt>List</tt>. You can refer to a value <tt>val</tt> stored at a<br />
node as <tt>@val</tt>. For instance, write <tt>@head</tt> to refer to the float stored in<br />
at a <tt>Cons</tt> node. Draw the corresponding picture if you're stuck.<br />
<br />
Now we've defined <tt>length</tt> and <tt>sum</tt>, let's compute the average. We'll know<br />
the sum and the length of the entire list at the Root node. Using those<br />
attributes we can compute the average and ''broadcast'' the average through<br />
the rest of the list. Let's start with the picture this time:<br />
<br />
[[Image:WAGM-Length.png|The average attribute]]<br />
<br />
The previous synthesized attributes, <tt>length</tt> and <tt>sum</tt>, defined bottom-up<br />
computations. We're now in the situation, however, where we want to pass<br />
information through the tree from a parent node to its child nodes using an<br />
''inherited'' attribute. Listing Five defines an inherited attribute <tt>avg</tt><br />
that corresponds to the picture we just drew.<br />
<br />
<haskell><br />
--- Listing Five ---<br />
ATTR List [ avg : Float|| ]<br />
SEM Root<br />
| Root list.avg = @list.sum / @list.length<br />
<br />
SEM List<br />
| Cons tail.avg = @lhs.avg<br />
<br />
</haskell><br />
<br />
Inherited attributes are declared to the left of the two vertical<br />
bars. Once we've declared an inherited attribute <tt>avg</tt> on lists, we're<br />
obliged to define how every constructor passes an <tt>avg</tt> to its children of<br />
type <tt>List</tt>.<br />
<br />
In our example, there are only two constructors with children<br />
of type <tt>List</tt>, namely <tt>Root</tt> and <tt>Cons</tt>. At the <tt>Root</tt> we compute the<br />
average, using the synthesized attributes <tt>sum</tt> and <tt>length</tt>, and pass the<br />
result to the <tt>list</tt> child. At the <tt>Cons</tt> node, we merely copy down the<br />
<tt>avg</tt> we received from our parent. Analogous to synthesized attributes, we<br />
can refer to an inherited attribute <tt>attr</tt> by writing <tt>@lhs.attr</tt>.<br />
<br />
Admittedly, this inherited attribute is not terribly interesting. There are<br />
plenty of other examples, however, where an inherited attribute represents<br />
important contextual information. Think of passing around the set of<br />
assumptions when writing a type checker, for instance.<br />
<br />
'''Exercise:''' To complete the attribute grammar, define an attribute<br />
<tt>res</tt> that computes the resulting list. Should it be inherited or<br />
synthesized? You may want to draw a picture.<br />
<br />
===Running the UUAG===<br />
Now suppose you've completed the exercises and copied the examples in a<br />
single file called <tt>Diff.ag</tt>. How do we actually use the attribute grammar?<br />
This is were the UUAG compiler steps in. Running the UUAG compiler on the<br />
source attribute grammar file generates a new <tt>Diff.hs</tt> file, which we can<br />
then compile like any other Haskell file.<br />
<br />
<haskell><br />
> uuagc -a Diff.ag<br />
> ghci Diff.hs<br />
</haskell><br />
<br />
The <tt>Diff.hs</tt> file contains several ingredients.<br />
<br />
Firstly, new Haskell datatypes are generated corresponding to <tt>DATA</tt><br />
declarations in the attribute grammar. For every generated datatype a<br />
corresponding <tt>fold</tt> is generated. The attribute definitions determine the<br />
arguments passed to the folds. Browsing through the generated code can<br />
actually be quite instructive.<br />
<br />
Inherited attributes are passed to recursive calls of the fold. Synthesized<br />
attributes are tupled and returned as the result of the computation. In<br />
essence, we've reproduced our original solution in Listing Two - but now<br />
without the hassle associated with spelling out [[catamorphism]]s with a higher<br />
order domain and a compound codomain.<br />
<br />
The attribute grammar solution is just as efficient as our earlier solution<br />
relying on lazy evaluation, yet the code is hardly different from what we<br />
would write in a straightforward Haskell solution. It really is the best of<br />
both worlds. The two types of glue that John Hughes pinpoints in his<br />
original article just aren't enough. I would like to think that sometimes<br />
attribute grammars are sometimes capable of providing just the right<br />
missing bit of glue.<br />
<br />
===What are attribute grammars?===<br />
So just what are attribute grammars? Well, that depends on who you ask,<br />
really. I've tried to sum up some different views below.<br />
<br />
Attribute grammars add semantics to a context free grammar. Although it is<br />
easy enough to describe a language's syntax using a context free grammar,<br />
accurately describing a language's semantics is notoriously<br />
difficult. Attribute grammars specify a language's semantics by<br />
'decorating' a context free grammar with those attributes you are interested<br />
in.<br />
<br />
Attribute grammars describe tree traversals. All imperative implementations<br />
of attribute grammar systems perform tree traversals to compute some<br />
value. Basically an attribute grammar declares ''which'' values to compute<br />
and an attribute grammar system executes these computations. Once you've<br />
made this observation, the close relation to functional programming should<br />
not come as a surprise.<br />
<br />
Attribute grammars are a formalism for writing catamorphisms in a<br />
compositional fashion. Basically, the only thing the UUAG compiler does is<br />
generate large folds that I couldn't be bothered writing myself. It takes<br />
away all the elbow grease involved with maintaining and extending such<br />
code. In a sense the compiler does absolutely nothing new; it just makes<br />
life a lot easier.<br />
<br />
Attribute grammars provide framework for aspect oriented programming in<br />
functional languages. Lately there has been a lot of buzz about the<br />
importance of ''aspects'' and ''aspect oriented programming''. Attribute<br />
grammars provide a clear and well-established framework for splitting code<br />
into separate aspects. By spreading attribute definitions over several<br />
different files and grouping them according to aspect, attribute grammars<br />
provide a natural setting for aspect oriented programming.<br />
<br />
How do attribute grammars relate to other Haskell abstractions? I'll try to<br />
put my finger on some of the more obvious connections, but I'm pretty sure<br />
there's a great deal more that I don't cover here.<br />
<br />
==What else is out there?==<br />
Everyone loves monads. They're what makes IO possible in Haskell. There are<br />
extensive standard libraries and syntactic sugar specifically designed to<br />
make life with monads easier. There are an enormous number of Haskell<br />
libraries based on the monadic interface. They represent one of the most<br />
substantial developments of functional programming in the last decade.<br />
<br />
Yet somehow, the single most common question asked by fledgling Haskell<br />
programmers is probably ''What are monads?''. Beginners have a hard time<br />
grasping the concept of monads and yet connoisseurs recognize a monad in<br />
just about every code snippet. I think the more important question is:<br />
''What are monads good for?''<br />
<br />
Monads provide a simple yet powerful abstract notion of computation. In<br />
essence, a monad describes how sequence computations. This is crucial in<br />
order to perform IO in a functional language; by constraining all IO<br />
actions to a single interface of sequenced computations, the programmer is<br />
prevented from creating utter chaos. The real power of monads is in the<br />
interface they provide.<br />
<br />
John Hughes identified modularity as the single biggest blessing of<br />
functional programming. The obvious question is: how modular is the monadic<br />
interface? This really depends on you're definition of modularity. Let me<br />
be more specific. How can you combine two arbitrary monads? You can't. This<br />
is my greatest concern with monads. Once you choose your specific notion of<br />
computation, you have to stick to it through thick and thin.<br />
<br />
What about monad transformers? Monad transformers allow you to add a<br />
specific monad's functionality on top of any existing monad. What seems<br />
like a solution, more often than not, turns out to introduce more problems<br />
than you bargained for. Adding new functionality to a monad involves<br />
lifting all the computations from the previous monad to the new<br />
one. Although I could learn to live with this, it gets even worse. As every<br />
monad transformer really changes the underlying monad. The order in<br />
which monad transformers are applied really makes a difference. If I want<br />
to add error reporting and state to some existing monad, should I be forced<br />
to consider the order in which I add them?<br />
<br />
Monads are extremely worthwhile for the interface they provide. Monadic<br />
libraries are great, but changing and extending monadic code can be a<br />
pain. Can we do better? Well I probably wouldn't have started this monadic<br />
intermezzo if I didn't have some sort of answer.<br />
<br />
Let's start off with <tt>Reader</tt> monads, for instance. Essentially, <tt>Reader</tt><br />
monads adds an argument to some computation. Wait a minute, this reminds me<br />
of inherited attributes. What about <tt>Writer</tt> monads? They correspond to<br />
synthesized attributes of course. Finally, <tt>State</tt> monads correspond to<br />
''chained'' attributes, or attributes that are both synthesized and<br />
inherited. The real edge attribute grammars hold over monad transformers is that you<br />
can define new attributes ''without'' worrying about the order in which you<br />
define them or adapting existing code.<br />
<br />
Do other abstractions capture other notions related to attribute grammars?<br />
Of course they do! Just look at the function space arrows instance. The notion of<br />
combining two distinct computations using the <tt>(&&&)</tt> operator relates to<br />
the concept of ''joining'' two attribute grammars by collecting their<br />
attribute definitions. When you look at the <tt>loop</tt> combinator, I can<br />
only be grateful that an attribute grammar system deals with attribute<br />
dependencies automatically.<br />
<br />
There really is a lot of related work. Implicit parameters? Inherited attributes! Linear implicit parameters? Chained attributes! Concepts that are so natural in the setting of attribute grammars, yet seem contrived when added to Haskell. This strengthens my belief that functional programmers can really benefit from even the most fleeting experience with attribute grammars; although I'd like to think that if you've read this far, you're hungry for more.<br />
<br />
==Further reading==<br />
This more or less covers the tutorial section of this article. The best way<br />
to learn more about attribute grammars is by actually using them. To conclude the tutorial, I've<br />
included a small example for you to play with. I've written a parser for a very<br />
simple wiki formatting language not entirely unlike the one used to produce this<br />
document. So far the HTML generated after parsing a document is fairly poor. It's up to<br />
you to improve it!<br />
<br />
You can download the initial version here. Don't forget to install the [http://www.cs.uu.nl/wiki/Center/AttributeGrammarSystem#Download UUAG]. It might<br />
be worthwhile to have a look at the [http://www.cs.uu.nl/~arthurb/data/AG/AGman.html UUAG manual] as there's a lot of technical detail that I haven't mentioned.<br />
<br />
If you're particularly daring, you may want to take a look at the [http://www.cs.uu.nl/wiki/Ehc/WebHome Essential Haskell Compiler] being developed at Utrecht. It's almost completely written using the UUAG and is designed to be suitable for education and experimentation. The compiler was presented at the Summer School for Advanced Functional Programming in Tartu, Estonia last summer. As a result, there's a lot written about it already.<br />
<br />
Dive on in!<br />
<br />
[[Category:Article]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=The_Monad.Reader/Issue4/Why_Attribute_Grammars_Matter&diff=28403The Monad.Reader/Issue4/Why Attribute Grammars Matter2009-05-30T03:56:09Z<p>Jsnx: Indentation helps a bit, here.</p>
<hr />
<div>=Why Attribute Grammars Matter=<br />
:''by Wouter Swierstra for The Monad.Reader Issue Four''; 01-07-05<br />
<br />
==Introduction==<br />
Almost twenty years have passed since John Hughes influential paper [http://www.math.chalmers.se/~rjmh/Papers/whyfp.html Why Functional Programming Matters]. At the same time the first work on<br />
attribute grammars and their relation to functional programming<br />
appeared. Despite the growing popularity of functional programming,<br />
attribute grammars remain remarkably less renown.<br />
<br />
The purpose of this article is twofold. On the one hand it illustrates how<br />
functional programming sometimes scales poorly and how<br />
attribute grammars can remedy these problems. On the other hand it aims to<br />
provide a gentle introduction to attribute grammars for seasoned functional<br />
programmers.<br />
<br />
==The problem==<br />
John Hughes argues that with the increasing complexity of modern<br />
software systems, modularity has become of paramount importance to software<br />
development. Functional languages provide new kinds of ''glue'' that create<br />
new opportunities for more modular code. In particular, Hughes stresses<br />
the importance of higher-order functions and lazy evaluation. There are<br />
plenty of examples where this works nicely - yet situations arise where<br />
the glue that functional programming provides somehow isn't quite enough.<br />
<br />
Perhaps a small example is in order. Suppose we want to write a function<br />
<tt>diff :: [Float] -> [Float]</tt> that given a list <tt>xs</tt>, calculates a new list where every element <tt>x</tt> is replaced with the difference between <tt>x</tt> and the<br />
average of <tt>xs</tt>. Similar problems pop up in any library for performing<br />
statistical calculations.<br />
<br />
===Higher-order functions===<br />
Let's tackle the problem with some of Haskell's most powerful glue - higher-order functions. Any beginning Haskell programmer should be able to concoct the solution presented in Listing One. The average is computed using functions from the Prelude. The obvious function using this average is then mapped over the original list. So far, so good.<br />
<br />
<haskell><br />
--- Listing One ---<br />
<br />
diff :: [Float] -> [Float]<br />
diff xs = map (\x -> x - (avg xs)) xs<br />
<br />
avg :: [Float] -> Float<br />
avg xs = sum xs / genericLength xs<br />
</haskell><br />
<br />
There are, however, a few things swept under the rug in this example. First<br />
of all, this simple problem requires three traversals of the original<br />
list. Computing additional values from the original list will require even<br />
more traversals.<br />
<br />
Secondly, the solution is so concise because it depends on Prelude<br />
functions. If the values were stored in a slightly different data structure,<br />
the solution would require a lot of tedious work. We could, of course,<br />
define our own higher-order functions, such as <tt>map</tt> and <tt>fold</tt>, or even<br />
resort to generic programming. There are, however,<br />
more ways to skin this particular cat.<br />
<br />
This problem illustrates the sheer elegance of functional programming. We<br />
do pay a price for the succinctness of the solution. Multiple traversals<br />
and boilerplate code can both be quite a head-ache. If we want to perform<br />
complex computations over custom data structures, we may want to consider an<br />
alternative approach.<br />
<br />
Fortunately, as experienced functional programmers, we have another card up<br />
our sleeve.<br />
<br />
===Lazy evaluation===<br />
The second kind of glue that functional programming provides is lazy<br />
evaluation. In essence, lazy evaluation only evaluates expressions when<br />
they become absolutely necessary.<br />
<br />
In particular, lazy evaluation enables the definition of ''circular programs'' that bear a dangerous resemblance to undefined values. Circular<br />
programs tuple separate computations, relying on lazy evaluation to feed<br />
the results of one computation to another.<br />
<br />
In our example, we could simply compute the length and sum of the list at<br />
the same time:<br />
<br />
<haskell><br />
average :: [Float] -> Float<br />
average xs = let<br />
nil = (0.0, 0.0)<br />
cons x (s,l) = (x + s, 1.0 + l)<br />
(sum,length) = foldr cons nil xs<br />
in sum / length<br />
</haskell><br />
<br />
We can eliminate traversals by tupling computations! Can we compute the<br />
resulting list at the same time as computing the sum and length? Let's try:<br />
<br />
<haskell><br />
diff :: [Float] -> [Float]<br />
diff xs = let<br />
nil = (0.0, 0.0, [])<br />
cons x (s,l,rs) = (x+s, 1.0+l, (x - ....) : rs)<br />
(sum,length,res) = foldr cons nil xs<br />
in res<br />
</haskell><br />
<br />
We run into trouble when we try to use the average to construct the<br />
resulting list. The problem is, that we haven't computed the average, but<br />
somehow want to use it during the traversal. To solve this, we don't actually<br />
compute the resulting list, but rather compute a function taking the<br />
average to the resulting list:<br />
<br />
<haskell><br />
diff :: [Float] -> [Float]<br />
diff xs =<br />
let<br />
nil = (0.0, 0.0, \avg -> [])<br />
cons x (s,l,rs) = (x+s, 1.0+l, \avg -> (x - avg) : rs avg)<br />
(sum,length,res) = foldr cons nil xs<br />
in<br />
res (sum / length)<br />
</haskell><br />
<br />
We can generalize this idea a bit further. Suppose that we want to compute<br />
other values that use the average. We could just add an <tt>avg</tt> argument to<br />
every element of the tuple that needs the average. It is a bit nicer,<br />
however, to lift the <tt>avg</tt> argument outside the tuple. Our final listing<br />
now becomes:<br />
<br />
<haskell><br />
--- Listing Two ---<br />
<br />
diff :: [Float] -> [Float]<br />
diff xs =<br />
let<br />
nil avg = (0.0, 0.0, [])<br />
cons x fs avg =<br />
let<br />
(s,l,ds) = fs avg<br />
in<br />
(s+x,l+1.0,x-avg : ds)<br />
(sum,length,ds) = foldr cons nil xs (sum / length)<br />
in<br />
ds<br />
</haskell><br />
<br />
Now every element of the tuple can refer to the average, rather than just<br />
the final list.<br />
<br />
This ''credit card transformation'' eliminates multiple traversals by<br />
tupling computations. We use the average without worrying if we have<br />
actually managed to compute it. When we actually write the fold, however,<br />
we have to put our average where our mouth is. Fortunately, the <tt>sum</tt> and<br />
<tt>length</tt> don't depend on the average, so we are free to use these values to<br />
tie the recursive knot.<br />
<br />
The code in Listing Two only needs a single traversal and one<br />
higher-order function. It apparently solves the problems with the code in<br />
Listing One.<br />
<br />
Hold on a minute. What ever happened to the elegance of our previous<br />
solution? Our second solution appears to have sacrificed clarity for the<br />
sake of efficiency. Who in their right minds would want to write the code<br />
in Listing Two? I wouldn't. Maybe, just maybe, we can do a bit better.<br />
<br />
==Attribute Grammars==<br />
Before even explaining what an attribute grammar is, think back to when you<br />
first learned about ''folds''. Initially, a fold seems like a silly<br />
abstraction. Why should I bother writing simple functions as folds? After<br />
all, I already know how to write the straightforward solution. It's only<br />
after a great deal of experience with functional programming that you learn<br />
to recognize folds as actually being a worthwhile abstraction. Learning<br />
about attribute grammars is similar in more ways than one.<br />
<br />
So what are attribute grammars? I'll have a bit more to say about that<br />
later. For now, let's see what the attribute grammar solution to our<br />
running example looks like.<br />
<br />
===The attribute grammar solution===<br />
I'll introduce attribute grammars using the syntax of the [http://www.cs.uu.nl/wiki/Center/AttributeGrammarSystem Utrecht University Attribute Grammar] system or UUAG for short. The UUAG system takes a file<br />
containing an attribute grammar definition and generates a Haskell module<br />
containing ''semantic functions'', determined by the attribute grammar. The<br />
attribute grammar determines a computation over some data structure; the<br />
semantic functions correspond to the actual Haskell functions that perform<br />
the computation.<br />
<br />
Although the UUAG system's syntax closely resembles Haskell, it is<br />
important to realize that the UUAG system is a Haskell pre-processor and<br />
not a complete Haskell compiler.<br />
<br />
So what does an attribute grammar file look like? Well, first of all we<br />
have to declare the data structure we're working with. In our example, we<br />
simply have a list of Floats.<br />
<br />
<haskell><br />
--- Listing Three ---<br />
<br />
DATA Root<br />
| Root list : List<br />
DATA List<br />
| Nil<br />
| Cons head : Float tail : List<br />
</haskell><br />
<br />
Datatypes are declared with the keyword <tt>DATA</tt>, followed by a list of<br />
constructors. Every node explicitly gives the name and type of all its<br />
children. In our example we have an empty list <tt>Nil</tt> and a list constructor<br />
<tt>Cons</tt> with two children, <tt>head</tt> and <tt>tail</tt>. For reasons that will become<br />
apparent later on, we add an additional datatype corresponding to the root<br />
of our list.<br />
<br />
So now that we've declared our datatype, let's add some ''attributes''. If we<br />
want to compute the average element, we'll need the length of the<br />
list. Listing Four contains introduces our first attribute corresponding to<br />
a list's length.<br />
<br />
<haskell><br />
--- Listing Four ---<br />
<br />
ATTR List [|| length : Float]<br />
SEM List<br />
| Nil lhs.length = 0.0<br />
| Cons lhs.length = 1.0 + @tail.length<br />
</haskell><br />
<br />
Let's go over the code line by line.<br />
<br />
An attribute has to be declared before it can actually be defined. An<br />
attribute is declared using the <tt>ATTR</tt> statement. This example declares a<br />
single ''synthesized'' attribute called <tt>length</tt> of type <tt>Float</tt>. A<br />
synthesized attribute is typically a value you are trying to compute bottom<br />
up. Synthesized attributes are declared to the right of the second<br />
vertical bar. We'll see other kinds attributes shortly.<br />
<br />
Now that we've declared our first attribute, we can actually define it. A<br />
<tt>SEM</tt> statement begins by declaring for which data type attributes are<br />
being defined. In our example we want to define an attribute on a <tt>List</tt>,<br />
hence we write <tt>SEM List</tt>. We can subsequently give attribute definitions<br />
for the constructors of our <tt>List</tt> data type.<br />
<br />
Every attribute definition consists of several parts. We begin by<br />
mentioning the constructor for which we define an attribute. In our example<br />
we give two definitions, one for <tt>Nil</tt> and one for <tt>Cons</tt>.<br />
<br />
The second part of the attribute definition describes which attribute is<br />
being defined. In our example we define the attribute <tt>length</tt> for the<br />
''left-hand side'', or <tt>lhs</tt>. A lot of the terminology associated with<br />
attribute grammars comes from the world of context-free grammars. As this<br />
tutorial focuses on functional programmers, rather than formal language<br />
gurus, feel free to read <tt>lhs</tt> as "parent node". It seems a bit odd to<br />
write <tt>lhs.length</tt> explicitly, but we'll see later on why merely writing<br />
<tt>length</tt> doesn't suffice.<br />
<br />
Basically, all we've only said that the two definitions define the <tt>length</tt><br />
of <tt>Nil</tt> and <tt>Cons</tt>. We still have to fill in the necessary definition. The<br />
actual definition of the attributes takes place to the right of the equals<br />
sign. Programmers are free to write any valid Haskell expression. In fact,<br />
the UUAG system does not analyse the attribute definitions at all, but merely<br />
copies them straight into the resulting Haskell module. In our example, we<br />
want the length of the empty list to be <tt>0.0</tt>. The case for <tt>Cons</tt> is a bit<br />
trickier.<br />
<br />
In the <tt>Cons</tt> case we want to be increment the length computed so far. To<br />
do so we need to be able to refer to other attributes. In particular we<br />
want to refer to the <tt>length</tt> attribute of the tail. The expression<br />
<tt>@tail.length</tt> does just that. In general, you're free to refer to any<br />
synthesized attribute ''attr'' of a child node ''c'' by writing <tt>@c.attr</tt>.<br />
<br />
The <tt>length</tt> attribute can be depicted pictorally as follows:<br />
<br />
[[Image:WAGM-Avg.png|The length attribute]]<br />
<br />
'''Exercise:''' Declare and define a synthesized attribute <tt>sum</tt> that<br />
computes the sum of a <tt>List</tt>. You can refer to a value <tt>val</tt> stored at a<br />
node as <tt>@val</tt>. For instance, write <tt>@head</tt> to refer to the float stored in<br />
at a <tt>Cons</tt> node. Draw the corresponding picture if you're stuck.<br />
<br />
Now we've defined <tt>length</tt> and <tt>sum</tt>, let's compute the average. We'll know<br />
the sum and the length of the entire list at the Root node. Using those<br />
attributes we can compute the average and ''broadcast'' the average through<br />
the rest of the list. Let's start with the picture this time:<br />
<br />
[[Image:WAGM-Length.png|The average attribute]]<br />
<br />
The previous synthesized attributes, <tt>length</tt> and <tt>sum</tt>, defined bottom-up<br />
computations. We're now in the situation, however, where we want to pass<br />
information through the tree from a parent node to its child nodes using an<br />
''inherited'' attribute. Listing Five defines an inherited attribute <tt>avg</tt><br />
that corresponds to the picture we just drew.<br />
<br />
<haskell><br />
--- Listing Five ---<br />
ATTR List [ avg : Float|| ]<br />
SEM Root<br />
| Root list.avg = @list.sum / @list.length<br />
<br />
SEM List<br />
| Cons tail.avg = @lhs.avg<br />
<br />
</haskell><br />
<br />
Inherited attributes are declared to the left of the two vertical<br />
bars. Once we've declared an inherited attribute <tt>avg</tt> on lists, we're<br />
obliged to define how every constructor passes an <tt>avg</tt> to its children of<br />
type <tt>List</tt>.<br />
<br />
In our example, there are only two constructors with children<br />
of type <tt>List</tt>, namely <tt>Root</tt> and <tt>Cons</tt>. At the <tt>Root</tt> we compute the<br />
average, using the synthesized attributes <tt>sum</tt> and <tt>length</tt>, and pass the<br />
result to the <tt>list</tt> child. At the <tt>Cons</tt> node, we merely copy down the<br />
<tt>avg</tt> we received from our parent. Analogous to synthesized attributes, we<br />
can refer to an inherited attribute <tt>attr</tt> by writing <tt>@lhs.attr</tt>.<br />
<br />
Admittedly, this inherited attribute is not terribly interesting. There are<br />
plenty of other examples, however, where an inherited attribute represents<br />
important contextual information. Think of passing around the set of<br />
assumptions when writing a type checker, for instance.<br />
<br />
'''Exercise:''' To complete the attribute grammar, define an attribute<br />
<tt>res</tt> that computes the resulting list. Should it be inherited or<br />
synthesized? You may want to draw a picture.<br />
<br />
===Running the UUAG===<br />
Now suppose you've completed the exercises and copied the examples in a<br />
single file called <tt>Diff.ag</tt>. How do we actually use the attribute grammar?<br />
This is were the UUAG compiler steps in. Running the UUAG compiler on the<br />
source attribute grammar file generates a new <tt>Diff.hs</tt> file, which we can<br />
then compile like any other Haskell file.<br />
<br />
<haskell><br />
> uuagc -a Diff.ag<br />
> ghci Diff.hs<br />
</haskell><br />
<br />
The <tt>Diff.hs</tt> file contains several ingredients.<br />
<br />
Firstly, new Haskell datatypes are generated corresponding to <tt>DATA</tt><br />
declarations in the attribute grammar. For every generated datatype a<br />
corresponding <tt>fold</tt> is generated. The attribute definitions determine the<br />
arguments passed to the folds. Browsing through the generated code can<br />
actually be quite instructive.<br />
<br />
Inherited attributes are passed to recursive calls of the fold. Synthesized<br />
attributes are tupled and returned as the result of the computation. In<br />
essence, we've reproduced our original solution in Listing Two - but now<br />
without the hassle associated with spelling out [[catamorphism]]s with a higher<br />
order domain and a compound codomain.<br />
<br />
The attribute grammar solution is just as efficient as our earlier solution<br />
relying on lazy evaluation, yet the code is hardly different from what we<br />
would write in a straightforward Haskell solution. It really is the best of<br />
both worlds. The two types of glue that John Hughes pinpoints in his<br />
original article just aren't enough. I would like to think that sometimes<br />
attribute grammars are sometimes capable of providing just the right<br />
missing bit of glue.<br />
<br />
===What are attribute grammars?===<br />
So just what are attribute grammars? Well, that depends on who you ask,<br />
really. I've tried to sum up some different views below.<br />
<br />
Attribute grammars add semantics to a context free grammar. Although it is<br />
easy enough to describe a language's syntax using a context free grammar,<br />
accurately describing a language's semantics is notoriously<br />
difficult. Attribute grammars specify a language's semantics by<br />
'decorating' a context free grammar with those attributes you are interested<br />
in.<br />
<br />
Attribute grammars describe tree traversals. All imperative implementations<br />
of attribute grammar systems perform tree traversals to compute some<br />
value. Basically an attribute grammar declares ''which'' values to compute<br />
and an attribute grammar system executes these computations. Once you've<br />
made this observation, the close relation to functional programming should<br />
not come as a surprise.<br />
<br />
Attribute grammars are a formalism for writing catamorphisms in a<br />
compositional fashion. Basically, the only thing the UUAG compiler does is<br />
generate large folds that I couldn't be bothered writing myself. It takes<br />
away all the elbow grease involved with maintaining and extending such<br />
code. In a sense the compiler does absolutely nothing new; it just makes<br />
life a lot easier.<br />
<br />
Attribute grammars provide framework for aspect oriented programming in<br />
functional languages. Lately there has been a lot of buzz about the<br />
importance of ''aspects'' and ''aspect oriented programming''. Attribute<br />
grammars provide a clear and well-established framework for splitting code<br />
into separate aspects. By spreading attribute definitions over several<br />
different files and grouping them according to aspect, attribute grammars<br />
provide a natural setting for aspect oriented programming.<br />
<br />
How do attribute grammars relate to other Haskell abstractions? I'll try to<br />
put my finger on some of the more obvious connections, but I'm pretty sure<br />
there's a great deal more that I don't cover here.<br />
<br />
==What else is out there?==<br />
Everyone loves monads. They're what makes IO possible in Haskell. There are<br />
extensive standard libraries and syntactic sugar specifically designed to<br />
make life with monads easier. There are an enormous number of Haskell<br />
libraries based on the monadic interface. They represent one of the most<br />
substantial developments of functional programming in the last decade.<br />
<br />
Yet somehow, the single most common question asked by fledgling Haskell<br />
programmers is probably ''What are monads?''. Beginners have a hard time<br />
grasping the concept of monads and yet connoisseurs recognize a monad in<br />
just about every code snippet. I think the more important question is:<br />
''What are monads good for?''<br />
<br />
Monads provide a simple yet powerful abstract notion of computation. In<br />
essence, a monad describes how sequence computations. This is crucial in<br />
order to perform IO in a functional language; by constraining all IO<br />
actions to a single interface of sequenced computations, the programmer is<br />
prevented from creating utter chaos. The real power of monads is in the<br />
interface they provide.<br />
<br />
John Hughes identified modularity as the single biggest blessing of<br />
functional programming. The obvious question is: how modular is the monadic<br />
interface? This really depends on you're definition of modularity. Let me<br />
be more specific. How can you combine two arbitrary monads? You can't. This<br />
is my greatest concern with monads. Once you choose your specific notion of<br />
computation, you have to stick to it through thick and thin.<br />
<br />
What about monad transformers? Monad transformers allow you to add a<br />
specific monad's functionality on top of any existing monad. What seems<br />
like a solution, more often than not, turns out to introduce more problems<br />
than you bargained for. Adding new functionality to a monad involves<br />
lifting all the computations from the previous monad to the new<br />
one. Although I could learn to live with this, it gets even worse. As every<br />
monad transformer really changes the underlying monad the ''order'' in<br />
which monad transformers are applied really makes a difference. If I want<br />
to add error reporting and state to some existing monad, should I be forced<br />
to consider the order in which I add them?<br />
<br />
Monads are extremely worthwhile for the interface they provide. Monadic<br />
libraries are great, but changing and extending monadic code can be a<br />
pain. Can we do better? Well I probably wouldn't have started this monadic<br />
intermezzo if I didn't have some sort of answer.<br />
<br />
Let's start off with <tt>Reader</tt> monads, for instance. Essentially, <tt>Reader</tt><br />
monads adds an argument to some computation. Wait a minute, this reminds me<br />
of inherited attributes. What about <tt>Writer</tt> monads? They correspond to<br />
synthesized attributes of course. Finally, <tt>State</tt> monads correspond to<br />
''chained'' attributes, or attributes that are both synthesized and<br />
inherited. The real edge attribute grammars hold over monad transformers is that you<br />
can define new attributes ''without'' worrying about the order in which you<br />
define them or adapting existing code.<br />
<br />
Do other abstractions capture other notions related to attribute grammars?<br />
Of course they do! Just look at the function space arrows instance. The notion of<br />
combining two distinct computations using the <tt>(&&&)</tt> operator relates to<br />
the concept of ''joining'' two attribute grammars by collecting their<br />
attribute definitions. When you look at the <tt>loop</tt> combinator, I can<br />
only be grateful that an attribute grammar system deals with attribute<br />
dependencies automatically.<br />
<br />
There really is a lot of related work. Implicit parameters? Inherited attributes! Linear implicit parameters? Chained attributes! Concepts that are so natural in the setting of attribute grammars, yet seem contrived when added to Haskell. This strengthens my belief that functional programmers can really benefit from even the most fleeting experience with attribute grammars; although I'd like to think that if you've read this far, you're hungry for more.<br />
<br />
==Further reading==<br />
This more or less covers the tutorial section of this article. The best way<br />
to learn more about attribute grammars is by actually using them. To conclude the tutorial, I've<br />
included a small example for you to play with. I've written a parser for a very<br />
simple wiki formatting language not entirely unlike the one used to produce this<br />
document. So far the HTML generated after parsing a document is fairly poor. It's up to<br />
you to improve it!<br />
<br />
You can download the initial version here. Don't forget to install the [http://www.cs.uu.nl/wiki/Center/AttributeGrammarSystem#Download UUAG]. It might<br />
be worthwhile to have a look at the [http://www.cs.uu.nl/~arthurb/data/AG/AGman.html UUAG manual] as there's a lot of technical detail that I haven't mentioned.<br />
<br />
If you're particularly daring, you may want to take a look at the [http://www.cs.uu.nl/wiki/Ehc/WebHome Essential Haskell Compiler] being developed at Utrecht. It's almost completely written using the UUAG and is designed to be suitable for education and experimentation. The compiler was presented at the Summer School for Advanced Functional Programming in Tartu, Estonia last summer. As a result, there's a lot written about it already.<br />
<br />
Dive on in!<br />
<br />
[[Category:Article]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Monad_laws&diff=28311Monad laws2009-05-25T11:33:19Z<p>Jsnx: Replaced `=` and `==` with `≡` where they indicate "identical to".</p>
<hr />
<div>All instances of the [[Monad]] class should obey:<br />
<br />
# "Left identity": <hask> return a >>= f ≡ f a </hask><br />
# "Right identity": <hask> m >>= return ≡ m </hask><br />
# "Associativity": <hask> (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) </hask><br />
<br />
<br />
== What is the practical meaning of the monad laws? ==<br />
<br />
Let us re-write the laws in do-notation:<br />
<br />
<haskell><br />
1. do { x' <- return x do { f x<br />
; f x' ≡ }<br />
}<br />
<br />
2. do { x <- m ≡ do { m<br />
; return x } }<br />
<br />
3. do { y <- do { x <- m do { x <- m<br />
; f x ; do { y <- f x<br />
} ≡ ; g y<br />
; g y }<br />
} }<br />
<br />
do { x <- m<br />
; y <- f x<br />
≡ ; g y<br />
}<br />
</haskell><br />
<br />
In this notation the laws appear as plain common sense.<br />
<br />
== But why should monads obey these laws? ==<br />
<br />
When we see a program written in a form on the LHS, we expect it to do<br />
the same thing as the corresponding RHS; and vice versa. And in<br />
practice, people do write like the lengthier LHS once in a while.<br />
First example: beginners tend to write<br />
<br />
<haskell><br />
skip_and_get = do { unused <- getLine<br />
; line <- getLine<br />
; return line<br />
}<br />
</haskell><br />
<br />
and it would really throw off both beginners and veterans if that did<br />
not act like (by law #2)<br />
<br />
<haskell><br />
skip_and_get = do { unused <- getLine<br />
; getLine<br />
}<br />
</haskell><br />
<br />
Second example: Next, you go ahead to use skip_and_get:<br />
<br />
<haskell><br />
main = do { answer <- skip_and_get<br />
; putStrLn answer<br />
}<br />
</haskell><br />
<br />
The most popular way of comprehending this program is by inlining<br />
(whether the compiler does or not is an orthogonal issue):<br />
<br />
<haskell><br />
main = do { answer <- do { unused <- getLine<br />
; getLine<br />
}<br />
; putStrLn answer<br />
}<br />
</haskell><br />
<br />
and applying law #3 so you can pretend it is<br />
<br />
<haskell><br />
main = do { unused <- getLine<br />
; answer <- getLine<br />
; putStrLn answer<br />
}<br />
</haskell><br />
<br />
Law #3 is amazingly pervasive: you have always assumed it, and you<br />
have never noticed it.<br />
<br />
Whether compilers exploit the laws or not, you still want the laws for<br />
your own sake, just so you can avoid pulling your hair for<br />
counter-intuitive program behaviour that brittlely depends on how many<br />
redundant "return"s you insert or how you nest your do-blocks.<br />
<br />
== But it doesn't look exactly like an "associative law"... ==<br />
<br />
Not in this form, no. To see precisely why they're called "identity laws" and an "associative law", you have to change your notation slightly.<br />
<br />
The monad composition operator (also known as the Kleisli composition operator) is defined in Control.Monad:<br />
<br />
<haskell><br />
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c<br />
m >=> n = \x -> do { y <- m x; n y }<br />
</haskell><br />
<br />
Using this operator, the three laws can be expressed like this:<br />
<br />
# "Left identity": <hask> return >=> g ≡ g </hask><br />
# "Right identity": <hask> f >=> return ≡ f </hask><br />
# "Associativity": <hask> (f >=> g) >=> h ≡ f >=> (g >=> h) </hask><br />
<br />
It's now easy to see that monad composition is an associative operator with left and right identities.<br />
<br />
This is a very important way to express the three monad laws, because they are precisely the laws that are required for monads to form a mathematical [[Category theory|category]]. So the monad laws can be summarised in convenient Haiku form:<br />
<br />
<blockquote><br />
Monad axioms:<br/><br />
Kleisli composition forms<br/><br />
a category.<br />
</blockquote><br />
<br />
[[Category:Standard_classes]]<br />
[[Category:Monad]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=GHC/Stand-alone_deriving_declarations&diff=28254GHC/Stand-alone deriving declarations2009-05-20T18:48:21Z<p>Jsnx: Links updated.</p>
<hr />
<div>[[Category:GHC|Stand-alone deriving declarations]]<br />
<br />
''This page is from an early point in the life of the stand-alone deriving mechanism. Please see the linked documentation for an up-to-date account of the present situation.''<br />
<br />
== Standalone deriving ==<br />
<br />
GHC supports so-called "stand-alone deriving" declarations, which are described in the [http://www.haskell.org/ghc/dist/current/docs/users_guide/deriving.html#stand-alone-deriving user manual section]. <br />
<br />
This page mentions points that may not be immediately obvious from the manual.<br />
<br />
== Deriving data types with non-standard contexts ==<br />
<br />
In Haskell 98, and GHC, you can't say this<br />
<haskell><br />
data T m = MkT (m Int) deriving Eq<br />
</haskell><br />
because the instance declaration would have a non-standard context. It would have to look like this:<br />
<haskell><br />
instance Eq (m Int) => Eq (T m) where ...<br />
</haskell><br />
Of course, you can write the instance manually, but then you have to write<br />
all that tiresome code for equality. Standalone deriving lets you supply the context yourself, but have GHC write the code:<br />
<haskell><br />
data T m = MkT (m Int)<br />
<br />
deriving instance Eq (m Int) => Eq (T m)<br />
</haskell><br />
Of course, you'll need to add the flags <hask>-XFlexibleContexts</hask> and <hask>-XUndecideableInstances</hask> to allow this instance declaration, but that's fair enough.<br />
<br />
The same applies to data type declarations involving type functions.<br />
<br />
== Variations (not implemented) ==<br />
<br />
This section collects some un-implemented ideas.<br />
<br />
=== Interaction with "newtype-deriving" ===<br />
<br />
GHC's "newtype deriving mechanism" (see [http://www.haskell.org/ghc/dist/current/docs/users_guide/deriving.html#newtype-deriving]) should obviously work in a standalone deriving setting too. But perhaps it can be generalised a little. Currently you can only say<br />
<haskell><br />
deriving instance C a Foo<br />
</haskell><br />
(where Foo is the newtype), and get an instance for <hask>(C a Foo)</hask>. But what if you want and instance for <hask>C Foo a</hask>, where the new type is not the last parameter. You can't do that at the moment. However, even with the new instance-like syntax, it's not clear to me how to signal the type to be derived. Consider<br />
<haskell><br />
newtype Foo = F Int<br />
newtype Bar = B Bool<br />
deriving instance C Foo Bar<br />
</haskell><br />
Which of these thee instances do we want?<br />
<haskell><br />
instance C Foo Bool => C Foo Bar<br />
instance C Int Bar => C Foo Bar<br />
instance C Int Bool => C Foo Bar<br />
</haskell><br />
The obvious way to signal this is to give the instance context (just as above). This is perhaps another reason for having an explicit instance context in a standalone deriving declaration.<br />
<br />
Incidentally, notice that the third of the alternatives in the previous bullet unwraps two newtypes simultaneously. John Meacham suggested this example:<br />
<haskell><br />
class SetLike m k where <br />
instance SetLike IntSet Int where<br />
<br />
newtype Id = Id Int<br />
newtype IdSet = IdSet IntSet<br />
<br />
deriving instance SetLike IntSet Int => SetLike IdSet Id<br />
</haskell><br />
<br />
=== Duplicate instances === <br />
<br />
Suppose two modules, M1 and M2 both contain an identical standalone deriving declaration<br />
<haskell><br />
deriving Show T<br />
</haskell><br />
Then, can you import M1 and M2 into another module X and use show on values of type T, or will you get an overlapping instance error? Since both instances are derived in the very same way, their code must be identical, so arguably we can choose either. (There is some duplicated code of course.)<br />
<br />
This situation is expected to be common, as the main use of the standalone feature is to obtain derived instances that were omitted when the data type was defined.<br />
<br />
But, that means whether or not an instance was derived is now part of the module's. Programs would be able to use this (mis)feature to perform a compile-time check and execute code differently depending on whether any given instance is derived or hand-coded:<br />
<haskell><br />
module MA(A) where<br />
data A = A deriving Show<br />
<br />
module MB(B) where<br />
data B = B deriving Show<br />
<br />
module MC where<br />
import MA<br />
import MB<br />
<br />
-- verify that the A and B Show instances were derived<br />
-- (they need to be derived to ensure the output can<br />
-- be parsed in our non-Haskell code).<br />
deriving instance Show A <br />
deriving instance Show B<br />
</haskell><br />
The writer of MC already knows that MA and MB defined instances of Show for A and B. He just wants to ensure that nobody changes either module to use a non-derived instance; if someone does try to use a non-derived instance:<br />
<haskell><br />
module MA(A) where<br />
data A = A<br />
instance Show A where<br />
show _ = "a"<br />
</haskell><br />
then they will get an overlapping instance error in MC. <br />
<br />
The result is that programs would be able to require, for any Class, not just that an instance of the class was defined for a type, but that a /derived/ instance was defined. Is this good?</div>Jsnxhttps://wiki.haskell.org/index.php?title=GHC/Stand-alone_deriving_declarations&diff=28253GHC/Stand-alone deriving declarations2009-05-20T18:40:06Z<p>Jsnx: Restored `a` in `C a Foo` example.</p>
<hr />
<div>[[Category:GHC|Stand-alone deriving declarations]]<br />
<br />
== Standalone deriving ==<br />
<br />
GHC supports so-called "stand-alone deriving" declarations, which are described in the [http://www.haskell.org/ghc/dist/current/docs/users_guide/type-extensions.html#stand-alone-deriving user manual section]. <br />
<br />
This page mentions points that may not be immediately obvious from the manual.<br />
<br />
== Deriving data types with non-standard contexts ==<br />
<br />
In Haskell 98, and GHC, you can't say this<br />
<haskell><br />
data T m = MkT (m Int) deriving Eq<br />
</haskell><br />
because the instance declaration would have a non-standard context. It would have to look like this:<br />
<haskell><br />
instance Eq (m Int) => Eq (T m) where ...<br />
</haskell><br />
Of course, you can write the instance manually, but then you have to write<br />
all that tiresome code for equality. Standalone deriving lets you supply the context yourself, but have GHC write the code:<br />
<haskell><br />
data T m = MkT (m Int)<br />
<br />
deriving instance Eq (m Int) => Eq (T m)<br />
</haskell><br />
Of course, you'll need to add the flags <hask>-XFlexibleContexts</hask> and <hask>-XUndecideableInstances</hask> to allow this instance declaration, but that's fair enough.<br />
<br />
The same applies to data type declarations involving type functions.<br />
<br />
== Variations (not implemented) ==<br />
<br />
This section collects some un-implemented ideas.<br />
<br />
=== Interaction with "newtype-deriving" ===<br />
<br />
GHC's "newtype deriving mechanism" (see [http://www.haskell.org/ghc/dist/current/docs/users_guide/type-extensions.html#newtype-deriving]) should obviously work in a standalone deriving setting too. But perhaps it can be generalised a little. Currently you can only say<br />
<haskell><br />
deriving instance C a Foo<br />
</haskell><br />
(where Foo is the newtype), and get an instance for <hask>(C a Foo)</hask>. But what if you want and instance for <hask>C Foo a</hask>, where the new type is not the last parameter. You can't do that at the moment. However, even with the new instance-like syntax, it's not clear to me how to signal the type to be derived. Consider<br />
<haskell><br />
newtype Foo = F Int<br />
newtype Bar = B Bool<br />
deriving instance C Foo Bar<br />
</haskell><br />
Which of these thee instances do we want?<br />
<haskell><br />
instance C Foo Bool => C Foo Bar<br />
instance C Int Bar => C Foo Bar<br />
instance C Int Bool => C Foo Bar<br />
</haskell><br />
The obvious way to signal this is to give the instance context (just as above). This is perhaps another reason for having an explicit instance context in a standalone deriving declaration.<br />
<br />
Incidentally, notice that the third of the alternatives in the previous bullet unwraps two newtypes simultaneously. John Meacham suggested this example:<br />
<haskell><br />
class SetLike m k where <br />
instance SetLike IntSet Int where<br />
<br />
newtype Id = Id Int<br />
newtype IdSet = IdSet IntSet<br />
<br />
deriving instance SetLike IntSet Int => SetLike IdSet Id<br />
</haskell><br />
<br />
=== Duplicate instances === <br />
<br />
Suppose two modules, M1 and M2 both contain an identical standalone deriving declaration<br />
<haskell><br />
deriving Show T<br />
</haskell><br />
Then, can you import M1 and M2 into another module X and use show on values of type T, or will you get an overlapping instance error? Since both instances are derived in the very same way, their code must be identical, so arguably we can choose either. (There is some duplicated code of course.)<br />
<br />
This situation is expected to be common, as the main use of the standalone feature is to obtain derived instances that were omitted when the data type was defined.<br />
<br />
But, that means whether or not an instance was derived is now part of the module's. Programs would be able to use this (mis)feature to perform a compile-time check and execute code differently depending on whether any given instance is derived or hand-coded:<br />
<haskell><br />
module MA(A) where<br />
data A = A deriving Show<br />
<br />
module MB(B) where<br />
data B = B deriving Show<br />
<br />
module MC where<br />
import MA<br />
import MB<br />
<br />
-- verify that the A and B Show instances were derived<br />
-- (they need to be derived to ensure the output can<br />
-- be parsed in our non-Haskell code).<br />
deriving instance Show A <br />
deriving instance Show B<br />
</haskell><br />
The writer of MC already knows that MA and MB defined instances of Show for A and B. He just wants to ensure that nobody changes either module to use a non-derived instance; if someone does try to use a non-derived instance:<br />
<haskell><br />
module MA(A) where<br />
data A = A<br />
instance Show A where<br />
show _ = "a"<br />
</haskell><br />
then they will get an overlapping instance error in MC. <br />
<br />
The result is that programs would be able to require, for any Class, not just that an instance of the class was defined for a type, but that a /derived/ instance was defined. Is this good?</div>Jsnxhttps://wiki.haskell.org/index.php?title=GHC/Stand-alone_deriving_declarations&diff=28252GHC/Stand-alone deriving declarations2009-05-20T12:57:27Z<p>Jsnx: Goofy syntax removed.</p>
<hr />
<div>[[Category:GHC|Stand-alone deriving declarations]]<br />
<br />
== Standalone deriving ==<br />
<br />
GHC supports so-called "stand-alone deriving" declarations, which are described in the [http://www.haskell.org/ghc/dist/current/docs/users_guide/type-extensions.html#stand-alone-deriving user manual section]. <br />
<br />
This page mentions points that may not be immediately obvious from the manual.<br />
<br />
== Deriving data types with non-standard contexts ==<br />
<br />
In Haskell 98, and GHC, you can't say this<br />
<haskell><br />
data T m = MkT (m Int) deriving Eq<br />
</haskell><br />
because the instance declaration would have a non-standard context. It would have to look like this:<br />
<haskell><br />
instance Eq (m Int) => Eq (T m) where ...<br />
</haskell><br />
Of course, you can write the instance manually, but then you have to write<br />
all that tiresome code for equality. Standalone deriving lets you supply the context yourself, but have GHC write the code:<br />
<haskell><br />
data T m = MkT (m Int)<br />
<br />
deriving instance Eq (m Int) => Eq (T m)<br />
</haskell><br />
Of course, you'll need to add the flags <hask>-XFlexibleContexts</hask> and <hask>-XUndecideableInstances</hask> to allow this instance declaration, but that's fair enough.<br />
<br />
The same applies to data type declarations involving type functions.<br />
<br />
== Variations (not implemented) ==<br />
<br />
This section collects some un-implemented ideas.<br />
<br />
=== Interaction with "newtype-deriving" ===<br />
<br />
GHC's "newtype deriving mechanism" (see [http://www.haskell.org/ghc/dist/current/docs/users_guide/type-extensions.html#newtype-deriving]) should obviously work in a standalone deriving setting too. But perhaps it can be generalised a little. Currently you can only say<br />
<haskell><br />
deriving instance C Foo<br />
</haskell><br />
(where Foo is the newtype), and get an instance for <hask>(C a Foo)</hask>. But what if you want and instance for <hask>C Foo a</hask>, where the new type is not the last parameter. You can't do that at the moment. However, even with the new instance-like syntax, it's not clear to me how to signal the type to be derived. Consider<br />
<haskell><br />
newtype Foo = F Int<br />
newtype Bar = B Bool<br />
deriving instance C Foo Bar<br />
</haskell><br />
Which of these thee instances do we want?<br />
<haskell><br />
instance C Foo Bool => C Foo Bar<br />
instance C Int Bar => C Foo Bar<br />
instance C Int Bool => C Foo Bar<br />
</haskell><br />
The obvious way to signal this is to give the instance context (just as above). This is perhaps another reason for having an explicit instance context in a standalone deriving declaration.<br />
<br />
Incidentally, notice that the third of the alternatives in the previous bullet unwraps two newtypes simultaneously. John Meacham suggested this example:<br />
<haskell><br />
class SetLike m k where <br />
instance SetLike IntSet Int where<br />
<br />
newtype Id = Id Int<br />
newtype IdSet = IdSet IntSet<br />
<br />
deriving instance SetLike IntSet Int => SetLike IdSet Id<br />
</haskell><br />
<br />
=== Duplicate instances === <br />
<br />
Suppose two modules, M1 and M2 both contain an identical standalone deriving declaration<br />
<haskell><br />
deriving Show T<br />
</haskell><br />
Then, can you import M1 and M2 into another module X and use show on values of type T, or will you get an overlapping instance error? Since both instances are derived in the very same way, their code must be identical, so arguably we can choose either. (There is some duplicated code of course.)<br />
<br />
This situation is expected to be common, as the main use of the standalone feature is to obtain derived instances that were omitted when the data type was defined.<br />
<br />
But, that means whether or not an instance was derived is now part of the module's. Programs would be able to use this (mis)feature to perform a compile-time check and execute code differently depending on whether any given instance is derived or hand-coded:<br />
<haskell><br />
module MA(A) where<br />
data A = A deriving Show<br />
<br />
module MB(B) where<br />
data B = B deriving Show<br />
<br />
module MC where<br />
import MA<br />
import MB<br />
<br />
-- verify that the A and B Show instances were derived<br />
-- (they need to be derived to ensure the output can<br />
-- be parsed in our non-Haskell code).<br />
deriving instance Show A <br />
deriving instance Show B<br />
</haskell><br />
The writer of MC already knows that MA and MB defined instances of Show for A and B. He just wants to ensure that nobody changes either module to use a non-derived instance; if someone does try to use a non-derived instance:<br />
<haskell><br />
module MA(A) where<br />
data A = A<br />
instance Show A where<br />
show _ = "a"<br />
</haskell><br />
then they will get an overlapping instance error in MC. <br />
<br />
The result is that programs would be able to require, for any Class, not just that an instance of the class was defined for a type, but that a /derived/ instance was defined. Is this good?</div>Jsnxhttps://wiki.haskell.org/index.php?title=Library/Data_encoding&diff=27840Library/Data encoding2009-04-22T20:01:51Z<p>Jsnx: Seemed to be a typo.</p>
<hr />
<div>[[Category:Libraries]]<br />
Data Encodings (dataenc): A collection of data encoding algorithms.<br />
<br />
== Data encodings library ==<br />
<br />
The data encodings library strives to provide implementations in Haskell of every major data encoding, and a few minor ones as well. Currently the following encodings are implemented:<br />
<br />
* Base16 (<hask>Codec.Binary.Base16</hask>)<br />
* Base32 (<hask>Codec.Binary.Base32</hask>)<br />
* Base32Hex (<hask>Codec.Binary.Base32Hex</hask>)<br />
* Base64 (<hask>Codec.Binary.Base64</hask>)<br />
* Base64Url (<hask>Codec.Binary.Base64Url</hask>)<br />
* Uuencode (<hask>Codec.Binary.Uu</hask>)<br />
<br />
In some cases the encodings also specify headers and footers for the encoded data. Implementation of that is left for the user of the library.<br />
<br />
== The API ==<br />
<br />
=== Main API ===<br />
<br />
The module <hask>Codec.Binary.DataEncoding</hask> provides a type that collects the functions for an individual encoding:<br />
<br />
<haskell><br />
data DataCodec = DataCodec {<br />
encode :: [Word8] -> String,<br />
decode :: String -> Maybe [Word8],<br />
decode' :: String -> [Maybe Word8],<br />
chop :: Int -> String -> [String],<br />
unchop :: [String] -> String<br />
}<br />
</haskell><br />
<br />
It also exposes instances of this type for each encoding:<br />
<br />
<haskell><br />
base16 :: DataCodec<br />
base32 :: DataCodec<br />
base32Hex :: DataCodec<br />
base64 :: DataCodec<br />
base64Url :: DataCodec<br />
uu :: DataCodec<br />
</haskell><br />
<br />
<b>NB</b> There is no instance for yEncoding since the functions in that module have slightly different type signatures.<br />
<br />
=== Secondary API ===<br />
<br />
Each individual encoding module is also exposed and offers four functions:<br />
<br />
<haskell><br />
encode :: [Word8] -> String<br />
decode :: String -> Maybe [Word8]<br />
decode' :: String -> [Maybe Word8]<br />
chop :: Int -> String -> [String]<br />
unchop :: [String] -> String<br />
</haskell><br />
<br />
== Description of the encodings ==<br />
<br />
=== Base16 ===<br />
<br />
Implemented as it's defined in [http://tools.ietf.org/html/rfc4648 RFC 4648].<br />
<br />
Each four bit nibble of an octet is encoded as a character in the set 0-9,A-F.<br />
<br />
=== Base32 ===<br />
<br />
Implemented as it's defined in [http://tools.ietf.org/html/rfc4648 RFC 4648].<br />
<br />
Five octets are expanded into eight so that only the five least significant bits are used. Each is then encoded into a 32-character encoding alphabet.<br />
<br />
=== Base32Hex ===<br />
<br />
Implemented as it's defined in [http://tools.ietf.org/html/rfc4648 RFC 4648].<br />
<br />
Just like Base32 but with a different encoding alphabet. Unlike Base64 and Base32, data encoded with Base32Hex maintains its sort order when the encoded data is compared bit wise.<br />
<br />
=== Base64 ===<br />
<br />
Implemented as it's defined in [http://tools.ietf.org/html/rfc4648 RFC 4648].<br />
<br />
Three octets are expanded into four so that only the six least significant bits are used. Each is then encoded into a 64-character encoding alphabet.<br />
<br />
=== Base64Url ===<br />
<br />
Implemented as it's defined in [http://tools.ietf.org/html/rfc4648 RFC 4648].<br />
<br />
Just like Base64 but with a different encoding alphabet. The encoding alphabet is made URL and filename safe by substituting <tt>+</tt> and <tt>/</tt> for <tt>-</tt> and <tt>_</tt> respectively.<br />
<br />
=== Uuencode ===<br />
<br />
Unfortunately uuencode is badly specified and there are in fact several differing implementations of it. This implementation attempts to encode data in the same way as the <tt>uuencode</tt> utility found in [http://www.gnu.org/software/sharutils/ GNU's sharutils]. The workings of <hask>chop</hask> and <hask>unchop</hask> also follow how sharutils split and unsplit encoded lines.<br />
<br />
=== yEncoding ===<br />
<br />
Implemented as it's defined in [http://yence.sourceforge.net/docs/protocol/version1_3_draft.html the 1.3 draft].<br />
<br />
== Downloading ==<br />
<br />
The current release is available from [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/dataenc HackageDB].<br />
<br />
See [[#Contributing]] below for how to get the development version.<br />
<br />
== Example of use ==<br />
<br />
The package [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/omnicodec omnicodec] contains two command line tools for encoding and decoding data.<br />
<br />
== Contributing ==<br />
<br />
Retrieve the source code using darcs like this:<br />
<br />
darcs get http://code.haskell.org/dataenc/devo dataenc<br />
<br />
Send any patches to magnus@therning.org</div>Jsnxhttps://wiki.haskell.org/index.php?title=GADTs_for_dummies&diff=27525GADTs for dummies2009-04-17T12:10:50Z<p>Jsnx: Disoriented.</p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Language extensions]]<br />
<br />
For a long time, I didn't understand what GADTs are and how they can be used. It was a sort of conspiracy of silence - people who understand GADTs think<br />
it is all obvious, and don't need any explanation, but I still<br />
couldn't understand.<br />
<br />
Now I have an idea how it works, and think that it was really obvious :) and I want to share my understanding - may be my way to realize GADTs can help<br />
someone else. See also [[Generalised algebraic datatype]]<br />
<br />
== Type functions ==<br />
<br />
A "data" declaration is a way to declare both type constructor and data<br />
constructors. For example,<br />
<br />
<haskell><br />
data Either a b = Left a | Right b<br />
</haskell><br />
<br />
declares type constructor "Either" and two data constructors "Left"<br />
and "Right". Ordinary Haskell functions works with data constructors:<br />
<br />
<haskell><br />
isLeft (Left a) = True<br />
isLeft (Right b) = False<br />
</haskell><br />
<br />
but there is also an analogous way to work with type constructors!<br />
<br />
<haskell><br />
type X a = Either a a<br />
</haskell><br />
<br />
declares a TYPE FUNCTION named "X". Its parameter "a" must be some type<br />
and it returns some type as its result. We can't use "X" on data values,<br />
but we can use it on type values. Type constructors declared with<br />
"data" statements and type functions declared with "type" statements<br />
used together to build arbitrarily complex types. In such<br />
"computations" type constructors serves as basic "values" and type<br />
functions as a way to process them.<br />
<br />
Indeed, type functions in Haskell are very limited compared to<br />
ordinary functions - they don't support pattern matching,<br />
nor multiple statements, nor recursion.<br />
<br />
== Hypothetical Haskell extension - Full-featured type functions ==<br />
<br />
Let's build hypothetical Haskell extension, that mimics for type<br />
functions the well-known ways to define ordinary functions, including<br />
pattern matching:<br />
<br />
<haskell><br />
type F [a] = Set a<br />
</haskell><br />
<br />
multiple statements (this is meaningful only in presence of pattern matching):<br />
<br />
<haskell><br />
type F Bool = Char<br />
F String = Int<br />
</haskell><br />
<br />
and recursion (which again needs pattern matching and multiple statements):<br />
<br />
<haskell><br />
type F [a] = F a<br />
F (Map a b) = F b<br />
F (Set a) = F a<br />
F a = a<br />
</haskell><br />
<br />
As you may already have guessed, this last definition calculates a simple base type of arbitrarily-nested collections, e.g.: <br />
<br />
<haskell><br />
F [[[Set Int]]] = <br />
F [[Set Int]] =<br />
F [Set Int] = <br />
F (Set Int) =<br />
F Int =<br />
Int<br />
</haskell><br />
<br />
Let's don't forget about statement guards:<br />
<br />
<haskell><br />
type F a | IsSimple a == TrueType = a<br />
</haskell><br />
<br />
Here we define type function F only for simple datatypes by using in<br />
guard type function "IsSimple":<br />
<br />
<haskell><br />
type IsSimple Bool = TrueType<br />
IsSimple Int = TrueType<br />
....<br />
IsSimple Double = TrueType<br />
IsSimple a = FalseType<br />
<br />
data TrueType = T<br />
data FalseType = F<br />
</haskell><br />
<br />
These definitions seem a bit odd, and while we are in imaginary land,<br />
let's consider a way to write this shorter:<br />
<br />
<haskell><br />
type F a | IsSimple a = a<br />
<br />
type IsSimple Bool<br />
IsSimple Int<br />
....<br />
IsSimple Double<br />
</haskell><br />
<br />
Here, we just defined list of simple types, the implied result of all<br />
written statements for "IsSimple" is True value, and False value for<br />
anything else. Essentially, "IsSimple" is no less than TYPE PREDICATE!<br />
<br />
I really love it! :) How about constructing a predicate that traverses a<br />
complex type trying to decide whether it contains "Int" anywhere?<br />
<br />
<haskell><br />
type HasInt Int<br />
HasInt [a] = HasInt a<br />
HasInt (Set a) = HasInt a<br />
HasInt (Map a b) | HasInt a<br />
HasInt (Map a b) | HasInt b<br />
</haskell><br />
<br />
or a type function that substitutes one type with another inside<br />
arbitrary-deep types:<br />
<br />
<haskell><br />
type Replace t a b | t==a = b<br />
Replace [t] a b = [Replace t a b]<br />
Replace (Set t) a b = Set (Replace t a b)<br />
Replace (Map t1 t2) a b = Map (Replace t1 a b) (Replace t2 a b)<br />
Replace t a b = t<br />
</haskell><br />
<br />
== One more hypothetical extension - multi-value type functions ==<br />
<br />
Let's add more fun! We will introduce one more hypothetical Haskell<br />
extension - type functions that may have MULTIPLE VALUES. Say,<br />
<br />
<haskell><br />
type Collection a = [a]<br />
Collection a = Set a<br />
Collection a = Map b a<br />
</haskell><br />
<br />
So, "Collection Int" has "[Int]", "Set Int" and "Map String Int" as<br />
its values, i.e. different collection types with elements of type<br />
"Int".<br />
<br />
Pay attention to the last statement of the "Collection" definition, where<br />
we've used type variable "b" that was not mentioned on the left side<br />
nor defined in any other way. It's perfectly possible - anyway<br />
"Collection" function has multiple values, so using on the right side<br />
some free variable that can be replaced with any type is not a problem<br />
at all - the "Map Bool Int", "Map [Int] Int" and "Map Int Int" all are<br />
possible values of "Collection Int" along with "[Int]" and "Set Int".<br />
<br />
At first glance, it seems that multiple-value functions are meaningless - they<br />
can't be used to define datatypes, because we need concrete types here. But on<br />
the second look :) we can find them useful to define type constraints and<br />
type families.<br />
<br />
We can also represent multiple-value function as predicate:<br />
<br />
<haskell><br />
type Collection a [a]<br />
Collection a (Set a)<br />
Collection a (Map b a)<br />
</haskell><br />
<br />
If you remember Prolog, you should guess that predicate, in contrast to<br />
function, is multi-purpose thing - it can be used to deduce any<br />
parameter from other ones. For example, in this hypothetical definition:<br />
<br />
<haskell><br />
head | Collection Int a :: a -> Int<br />
</haskell><br />
<br />
we define 'head' function for any Collection containing Ints.<br />
<br />
And in this, again, hypothetical definition:<br />
<br />
<haskell><br />
data Safe c | Collection c a = Safe c a<br />
</haskell><br />
<br />
we deduced element type 'a' from collection type 'c' passed as the<br />
parameter to the type constructor.<br />
<br />
<br />
<br />
== Back to real Haskell - type classes ==<br />
<br />
Reading all those glorious examples you may be wondering - why Haskell<br />
don't yet supports full-featured type functions? Hold your breath...<br />
Haskell already contains them and at least GHC implements all the<br />
mentioned abilities more than 10 years ago! They just was named...<br />
TYPE CLASSES! Let's translate all our examples to their language:<br />
<br />
<haskell><br />
class IsSimple a<br />
instance IsSimple Bool<br />
instance IsSimple Int<br />
....<br />
instance IsSimple Double<br />
</haskell><br />
<br />
Haskell'98 standard supports type classes with only one parameter that<br />
limits us to defining only type predicates like this one. But GHC and<br />
Hugs supports multi-parameter type classes that allows us to define<br />
arbitrarily-complex type functions<br />
<br />
<haskell><br />
class Collection a c<br />
instance Collection a [a]<br />
instance Collection a (Set a)<br />
instance Collection a (Map b a)<br />
</haskell><br />
<br />
All the "hypothetical" Haskell extensions we investigated earlier -<br />
actually implemented at the type class level!<br />
<br />
Pattern matching:<br />
<br />
<haskell><br />
instance Collection a [a]<br />
</haskell><br />
<br />
Multiple statements:<br />
<br />
<haskell><br />
instance Collection a [a]<br />
instance Collection a (Set a)<br />
</haskell><br />
<br />
Recursion:<br />
<br />
<haskell><br />
instance (Collection a c) => Collection a [c]<br />
</haskell><br />
<br />
Pattern guards:<br />
<br />
<haskell><br />
instance (IsSimple a) => Collection a (UArray a)<br />
</haskell><br />
<br />
<br />
<br />
Let's define type class which contains any collection which uses Int as<br />
its elements or indexes:<br />
<br />
<haskell><br />
class HasInt a<br />
instance HasInt Int<br />
instance (HasInt a) => HasInt [a]<br />
instance (HasInt a) => HasInt (Map a b)<br />
instance (HasInt b) => HasInt (Map a b)<br />
</haskell><br />
<br />
<br />
Anther example is a class that replaces all occurrences of 'a' with<br />
'b' in type 't' and return result as 'res':<br />
<br />
<haskell><br />
class Replace t a b res<br />
instance Replace t a a t<br />
instance Replace [t] a b [Replace t a b]<br />
instance (Replace t a b res)<br />
=> Replace (Set t) a b (Set res)<br />
instance (Replace t1 a b res1, Replace t2 a b res2)<br />
=> Replace (Map t1 t2) a b (Map res1 res2)<br />
instance Replace t a b t<br />
</haskell><br />
<br />
You can compare it to the hypothetical definition we gave earlier.<br />
It's important to note that type class instances, as opposite to<br />
function statements, are not checked in order. Instead, most<br />
_specific_ instance automatically selected. So, in Replace case, the<br />
last instance that is most general will be selected only if all other<br />
are failed to match and that is that we want.<br />
<br />
In many other cases this automatic selection is not powerful enough<br />
and we are forced to use some artificial tricks or complain to the<br />
language developers. The two most well-known language extensions<br />
proposed to solve such problems are instance priorities, which allow<br />
to explicitly specify instance selection order, and '/=' constraints,<br />
which can be used to explicitly prohibit unwanted matches:<br />
<br />
<haskell><br />
instance Replace t a a t<br />
instance (a/=b) => Replace [t] a b [Replace t a b]<br />
instance (a/=b, t/=[_]) => Replace t a b t<br />
</haskell><br />
<br />
You can check that these instances are no more overlaps.<br />
<br />
<br />
In practice, type-level arithmetic by itself is not very useful. It becomes a<br />
fantastic tool when combined with another feature that type classes provide -<br />
member functions. For example:<br />
<br />
<haskell><br />
class Collection a c where<br />
foldr1 :: (a -> a -> a) -> c -> a<br />
<br />
class Num a where<br />
(+) :: a -> a -> a<br />
<br />
sum :: (Num a, Collection a c) => c -> a<br />
sum = foldr1 (+)<br />
</haskell><br />
<br />
<br />
I'll be also glad to see possibility to use type classes in data<br />
declarations like this:<br />
<br />
<haskell><br />
data Safe c = (Collection c a) => Safe c a<br />
</haskell><br />
<br />
but afaik this is also not yet implemented<br />
<br />
<br />
UNIFICATION<br />
...<br />
<br />
<br />
<br />
== Back to GADTs ==<br />
<br />
If you are wonder how relates all these interesting type manipulations to<br />
GADTs, now you come to the answer. As you know, Haskell contains highly<br />
developed ways to express data-to-data functions. Now we also know that<br />
Haskell contains rich facilities to write type-to-type functions in form of<br />
"type" statements and type classes. But how do "data" statements fits in this<br />
infrastructure?<br />
<br />
My answer: they just defines type-to-data constructors translation. Moreover,<br />
this translation may give multiple results. Say, the following definition:<br />
<br />
<haskell><br />
data Maybe a = Just a | Nothing<br />
</haskell><br />
<br />
defines type-to-data constructors function "Maybe" that has parameter<br />
"a" and for each "a" has two possible results - "Just a" and<br />
"Nothing". We can rewrite it in the same hypothetical syntax that was<br />
used above for multi-value type functions:<br />
<br />
<haskell><br />
data Maybe a = Just a<br />
Maybe a = Nothing<br />
</haskell><br />
<br />
Or how about this:<br />
<br />
<haskell><br />
data List a = Cons a (List a)<br />
List a = Nil<br />
</haskell><br />
<br />
and this:<br />
<br />
<haskell><br />
data Either a b = Left a<br />
Either a b = Right b<br />
</haskell><br />
<br />
But how flexible are "data" definitions? As you should remember, "type"<br />
definitions was very limited in their features, while type classes, vice<br />
versa, much more developed than ordinary Haskell functions facilities. What<br />
about features of "data" definitions examined as sort of functions?<br />
<br />
On the one hand, they supports multiple statements and multiple results and<br />
can be recursive, like the "List" definition above. On the other, that's all -<br />
no pattern matching or even type constants on the left side and no guards.<br />
<br />
Lack of pattern matching means that left side can contain only free type<br />
variables, that in turn means that left sides of all "data" statements for one<br />
type will be essentially the same. Therefore, repeated left sides in<br />
multi-statement "data" definitions are omitted and instead of<br />
<br />
<haskell><br />
data Either a b = Left a<br />
Either a b = Right b<br />
</haskell><br />
<br />
we write just<br />
<br />
<haskell><br />
data Either a b = Left a<br />
| Right b<br />
</haskell><br />
<br />
<br />
And here finally comes the GADTs! It's just a way to define data types using<br />
pattern matching and constants on the left side of "data" statements! How<br />
about this:<br />
<br />
<haskell><br />
data T String = D1 Int<br />
T Bool = D2<br />
T [a] = D3 (a,a)<br />
</haskell><br />
<br />
Amazed? After all, GADTs seems really very simple and obvious extension to<br />
data type definition facilities.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The idea is to allow a data constructor's return type to be specified<br />
directly:<br />
<br />
<haskell><br />
data Term a where<br />
Lit :: Int -> Term Int<br />
Pair :: Term a -> Term b -> Term (a,b)<br />
...<br />
</haskell><br />
<br />
In a function that performs pattern matching on Term, the pattern match gives<br />
type as well as value information. For example, consider this function:<br />
<br />
<haskell><br />
eval :: Term a -> a<br />
eval (Lit i) = i<br />
eval (Pair a b) = (eval a, eval b)<br />
...<br />
</haskell><br />
<br />
If the argument matches Lit, it must have been built with a Lit constructor,<br />
so type 'a' must be Int, and hence we can return 'i' (an Int) in the right<br />
hand side. The same objections applies to the Pair constructor.<br />
<br />
<br />
<br />
<br />
<br />
<br />
== Further reading ==<br />
<br />
The best paper on type level arithmetic using type classes I've seen<br />
is "Faking it: simulating dependent types in Haskell"<br />
( http://www.cs.nott.ac.uk/~ctm/faking.ps.gz ). Most part of my<br />
article is just duplicates his work.<br />
<br />
The great demonstration of type-level arithmetic is TypeNats package<br />
which "defines type-level natural numbers and arithmetic operations on<br />
them including addition, subtraction, multiplication, division and GCD"<br />
( darcs get --partial --tag '0.1' http://www.eecs.tufts.edu/~rdocki01/typenats/ )<br />
<br />
I should also mention here Oleg Kiselyov page on type-level<br />
programming in Haskell: http://okmij.org/ftp/Haskell/types.html<br />
<br />
<br />
There are plenty of GADT-related papers, but best for beginners<br />
remains the "Fun with phantom types"<br />
(http://www.informatik.uni-bonn.de/~ralf/publications/With.pdf).<br />
Phantom types is another name of GADT. You should also know that this<br />
paper uses old GADT syntax. This paper is must-read because it<br />
contains numerous examples of practical GADT usage - theme completely<br />
omitted from my article.<br />
<br />
<br />
Other GADT-related papers i know:<br />
<br />
"Dynamic Optimization for Functional Reactive Programming using<br />
Generalized Algebraic Data Types"<br />
http://www.cs.nott.ac.uk/~nhn/Publications/icfp2005.pdf<br />
<br />
"Phantom types" (actually more scientific version of "Fun with phantom types")<br />
http://citeseer.ist.psu.edu/rd/0,606209,1,0.25,Download/http:qSqqSqwww.informatik.uni-bonn.deqSq~ralfqSqpublicationsqSqPhantom.ps.gz<br />
<br />
"Phantom types and subtyping" http://arxiv.org/ps/cs.PL/0403034<br />
<br />
"Existentially quantified type classes" by Stuckey, Sulzmann and Wazny (URL?)<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
== Random rubbish from previous versions of article ==<br />
<br />
<br />
<haskell><br />
data family Map k :: * -> *<br />
<br />
data instance Map () v = MapUnit (Maybe v)<br />
data instance Map (a, b) v = MapPair (Map a (Map b v))<br />
</haskell><br />
<br />
<br />
<br />
<br />
<br />
<br />
let's consider well-known 'data' declarations:<br />
<br />
<haskell><br />
data T a = D a a Int<br />
</haskell><br />
<br />
it can be seen as function 'T' from type 'a' to some data constructor.<br />
<br />
'T Bool', for example, gives result 'D Bool Bool Int', while<br />
<br />
'T [Int]' gives result 'D [Int] [Int] Int'.<br />
<br />
'data' declaration can also have several "results", say<br />
<br />
<haskell><br />
data Either a b = Left a | Right b<br />
</haskell><br />
<br />
and "result" of 'Either Int String' can be either "Left Int" or "Right<br />
String"<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Well, to give compiler confidence<br />
that 'a' can be deduced in just one way from 'c', we can add some<br />
form of hint:<br />
<br />
<haskell><br />
type Collection :: a c | c->a<br />
Collection a [a]<br />
Collection a (Set a)<br />
Collection a (Map b a)<br />
</haskell><br />
<br />
The first line i added tell the compiler that Collection predicate has<br />
two parameters and the second parameter determines the first. Based on<br />
this restriction, compiler can detect and prohibit attempts to define<br />
different element types for the same collection:<br />
<br />
<haskell><br />
type Collection :: a c | c->a<br />
Collection a (Map b a)<br />
Collection b (Map b a) -- error! prohibits functional dependency<br />
</haskell><br />
<br />
Of course, Collection is just a function from 'c' to 'a', but if we<br />
will define it directly as a function:<br />
<br />
<haskell><br />
type Collection [a] = a<br />
Collection (Set a) = a<br />
Collection (Map b a) = a<br />
</haskell><br />
<br />
- it can't be used in 'head' definition above. Moreover, using<br />
functional dependencies we can define bi-directional functions:<br />
<br />
<haskell><br />
type TwoTimesBigger :: a b | a->b, b->a<br />
TwoTimesBigger Int8 Int16<br />
TwoTimesBigger Int16 Int32<br />
TwoTimesBigger Int32 Int64<br />
</haskell><br />
<br />
or predicates with 3, 4 or more parameters with any relations between<br />
them. It's a great power!</div>Jsnxhttps://wiki.haskell.org/index.php?title=Nested_lambdas&diff=27410Nested lambdas2009-04-10T10:59:46Z<p>Jsnx: Looks retarded otherwise.</p>
<hr />
<div>== Problem ==<br />
<br />
Question:<br />
<br />
The following two lines seem to behave identical.<br />
Is there a substantive difference between them?<br />
<br />
<haskell><br />
\_ n -> 1 + n<br />
\_ -> (\n -> 1 + n)<br />
</haskell><br />
<br />
<br />
Answer:<br />
<br />
Actually the first line is [[syntactic sugar]] for the second one.<br />
<br />
<br />
== How GHC handles it ==<br />
<br />
You can check this out your self by compiling this program and<br />
looking at the generated core program like this:<br />
<br />
<haskell><br />
module Difference where<br />
<br />
foo :: Num b => a -> b -> b<br />
foo = \_ n -> 1 + n<br />
<br />
bar :: Num b => a -> b -> b<br />
bar = \_ -> (\n -> 1 + n)<br />
</haskell><br />
<br />
<br />
$ ghc -ddump-simpl Difference.hs<br />
<br />
==================== Tidy Core ====================<br />
Difference.bar :: forall b_a5j a_a5k.<br />
(GHC.Num.Num b_a5j) =><br />
a_a5k -> b_a5j -> b_a5j<br />
[GlobalId]<br />
[Arity 1<br />
NoCafRefs]<br />
Difference.bar =<br />
\ (@ b_a9E) (@ a_a9F) ($dNum_a9L :: GHC.Num.Num b_a9E) -><br />
let {<br />
lit_a9J :: b_a9E<br />
[]<br />
lit_a9J =<br />
case $dNum_a9L<br />
of tpl_B1<br />
{ GHC.Num.:DNum tpl1_B2<br />
tpl2_B3<br />
tpl3_B4<br />
tpl4_B5<br />
tpl5_B6<br />
tpl6_B7<br />
tpl7_B8<br />
tpl8_B9<br />
tpl9_Ba -><br />
tpl9_Ba (GHC.Num.S# 1)<br />
}<br />
} in<br />
\ (ds_dad :: a_a9F) (n_a79 :: b_a9E) -><br />
case $dNum_a9L<br />
of tpl_B1<br />
{ GHC.Num.:DNum tpl1_B2<br />
tpl2_B3<br />
tpl3_B4<br />
tpl4_B5<br />
tpl5_B6<br />
tpl6_B7<br />
tpl7_B8<br />
tpl8_B9<br />
tpl9_Ba -><br />
tpl3_B4 lit_a9J n_a79<br />
}<br />
<br />
Difference.foo :: forall b_a5m a_a5n.<br />
(GHC.Num.Num b_a5m) =><br />
a_a5n -> b_a5m -> b_a5m<br />
[GlobalId]<br />
[Arity 1<br />
NoCafRefs]<br />
Difference.foo =<br />
\ (@ b_aa0) (@ a_aa1) ($dNum_aa7 :: GHC.Num.Num b_aa0) -><br />
let {<br />
lit_aa5 :: b_aa0<br />
[]<br />
lit_aa5 =<br />
case $dNum_aa7<br />
of tpl_B1<br />
{ GHC.Num.:DNum tpl1_B2<br />
tpl2_B3<br />
tpl3_B4<br />
tpl4_B5<br />
tpl5_B6<br />
tpl6_B7<br />
tpl7_B8<br />
tpl8_B9<br />
tpl9_Ba -><br />
tpl9_Ba (GHC.Num.S# 1)<br />
}<br />
} in<br />
\ (ds_dae :: a_aa1) (n_a5q :: b_aa0) -><br />
case $dNum_aa7<br />
of tpl_B1<br />
{ GHC.Num.:DNum tpl1_B2<br />
tpl2_B3<br />
tpl3_B4<br />
tpl4_B5<br />
tpl5_B6<br />
tpl6_B7<br />
tpl7_B8<br />
tpl8_B9<br />
tpl9_Ba -><br />
tpl3_B4 lit_aa5 n_a5q<br />
}<br />
<br />
<br />
<br />
This looks very scary so let me try to explain:<br />
<br />
The Core language [2] (formally called System FC [3]) is actually very<br />
similar to Haskell because both are based on the lambda calculus. One<br />
imported difference is that in the Core language a function can take a<br />
type as an argument and it can be applied to a type. This is needed to<br />
implement polymorphic functions. <code>foo</code> and <code>bar</code> for example are<br />
polymorphic in all their arguments. This means that when you want to<br />
apply <code>foo</code> or <code>bar</code> to some arguments <code>x</code> and <code>y</code> you should first<br />
apply it to the types of <code>x</code> and <code>y</code>.<br />
<br />
Another major difference with Haskell is the way overloaded function<br />
are implemented. Note that in both <code>foo</code> and <code>bar</code> you use an<br />
overloaded literal <code>1</code><br />
(<code>1</code> is translated to <code>fromInteger 1</code>) and<br />
overloaded function <code>+</code>. The following quote from [3] explains briefly<br />
how overloaded functions are translated:<br />
<br />
"Generally, type classes are translated into SystemF [17] by (1) turning<br />
each class into a record type, called a dictionary, containing<br />
the class methods, (2) converting each instance into a dictionary<br />
value, and (3) passing such dictionaries to whichever<br />
function mentions a class in its signature."<br />
<br />
Now with this knowledge lets look at the Core output for <code>bar</code>:<br />
<br />
You see that <code>bar</code> is a lambda abstraction that takes the two types<br />
that we talked about: <code>@ b_a9E</code> <code>@ a_a9F</code> (the @ indicates that it are<br />
types) these correspond to the types <code>a</code> and <code>b</code> in our original<br />
Haskell program. The lambda abstraction also takes a third argument<br />
which is the dictionary we talked about:<br />
<code>$dNum_a9L :: GHC.Num.Num b_a9E</code> (the $ indicates that it's a<br />
dictionary). Note that the dictionary type constructor is applied to<br />
the type <code>b_a9E</code>.<br />
<br />
On to the body of the lambda abstraction. First you see that a<br />
variable <code>lit_a9J :: b_a9E</code> is defined. This is going to be the<br />
overloaded literal <code>1</code>. As I said when you write <code>1</code> in Haskell it is<br />
translated to <code>fromInteger 1</code> where <code>fromInteger</code> is an overloaded<br />
function (a method in the <code>Num</code> type class [4]) and <code>1</code> is a concrete<br />
<code>Integer</code>. Note that <code>bar</code> has received the dictionary for <code>Num</code> that<br />
contains all the methods of <code>Num</code> like <code>+</code>, <code>-</code> and <code>fromInteger</code>. The<br />
only thing we need to do is extract the right method (<code>fromInteger</code>)<br />
from the dictionary and apply it to a concrete Integer. This is what<br />
happens in the case expression: we extract the method <code>tpl9_Ba</code> and<br />
apply it to <code>GHC.Num.S# 1</code>.<br />
<br />
Now that our literal 1 is defined, a lambda abstraction is created<br />
that takes two arguments <code>ds_dad :: a_a9F</code> and <code>n_a79 :: b_a9E</code> which<br />
correspond to the arguments in our original Haskell program. Now the<br />
overloaded function <code>+</code> should be applied to the defined literal<br />
<code>lit_a9J</code> and the resulting function should be applied to the argument<br />
<code>n_a79</code>. Because <code>+</code> is overloaded the same thing happens as we saw<br />
with the overloaded literal <code>1</code>.<br />
<br />
Now that you can read GHC Core programs :-) you can observe that <code>foo</code><br />
and <code>bar</code> are the same.<br />
<br />
<br />
== References ==<br />
<br />
# http://www.haskell.org/ghc/dist/current/docs/users_guide/options-debugging.html<br />
# http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/CoreSynType<br />
# http://research.microsoft.com/%7Esimonpj/papers/ext%2Df/fc-tldi.pdf<br />
# http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3AfromInteger<br />
<br />
* Haskell-Cafe: [http://www.haskell.org/pipermail/haskell-cafe/2007-September/032035.html Spot the difference]<br />
<br />
[[Category:FAQ]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Twitter&diff=26842Twitter2009-03-03T07:46:27Z<p>Jsnx: added my screenname</p>
<hr />
<div>'''Haskell community members on Twitter'''<br />
<br />
* Bryan O’Sullivan ([http://twitter.com/bos31337 bos31337]) <br />
* Brandon Allbery ([http://twitter.com/geekosaur geekosaur]) <br />
* alpheccar ([http://twitter.com/alpheccar alpheccar])<br />
* Arnar Birgisson ([http://twitter.com/arnarbi arnarbi]) <br />
* Chris Eidhof ([http://twitter.com/chriseidhof chriseidhof]) <br />
* Conal Elliott ([http://twitter.com/conal conal]) <br />
* Conrad Parker ([http://twitter.com/conradparker conradparker]) <br />
* Don Stewart ([http://twitter.com/donsbot donsbot]) <br />
* Eelco Lempsink ([http://twitter.com/eelco eelco]) <br />
* Galois, Inc. ([http://twitter.com/galoisinc galoisinc]) <br />
* Jake McArthur ([http://twitter.com/geezusfreeek geezusfreeek]) <br />
* Pepe Iborra ([http://twitter.com/hate_pick_nick hate_pick_nick]) <br />
* John Goerzen ([http://twitter.com/jgoerzen jgoerzen]) <br />
* Eugene Kirpichov ([http://twitter.com/jkff jkff]) <br />
* Kazuya Sakakihara ([http://twitter.com/kazooya kazooya]) <br />
* Edward Kmett ([http://twitter.com/kmett kmett]) <br />
* Matthew Podwysocki ([http://twitter.com/mattpodwysocki mattpodwysocki]) <br />
* Mark Reid ([http://twitter.com/mdreid mdreid]) <br />
* Andy Adams-Moran ([http://twitter.com/morabbin morabbin]) <br />
* Neil Bartlett ([http://twitter.com/njbartlett njbartlett]) <br />
* Paul Brown ([http://twitter.com/paulrbrown paulrbrown]) <br />
* Shae Erisson ([http://twitter.com/shapr shapr]) <br />
* Sigbjorn Finne ([http://twitter.com/sigbjorn_finne sigbjorn_finne]) <br />
* Stefan Holdermans ([http://twitter.com/_dblhelix _dblhelix])<br />
* Dan Piponi ([http://twitter.com/sigfpe sigfpe]) <br />
* Spencer Janssen ([http://twitter.com/spencerjanssen spencerjanssen]) <br />
* Isaac Jones ([http://twitter.com/SyntaxPolice SyntaxPolice]) <br />
* Manuel Chakravarty ([http://twitter.com/TacticalGrace TacticalGrace]) <br />
* Tom Moertel ([http://twitter.com/tmoertel tmoertel]) <br />
* Thomas Sutton ([http://twitter.com/thsutton thsutton]) <br />
* Creighton Hogg ([http://twitter.com/wchogg wchogg]) <br />
* Jeff Wheeler ([http://twitter.com/jeffwheeler jeffwheeler])<br />
* Daniel Peebles ([http://twitter.com/pumpkingod pumpkingod], pumpkin on IRC)<br />
* Simon Marlow ([http://twitter.com/simonmar simonmar])<br />
* Andrew Wagner ([http://twitter.com/arwagner chessguy])<br />
* Magnus Therning ([http://twitter.com/magthe magthe])<br />
* Jan Xie ([http://twitter.com/flowerborn flowerborn])<br />
* Wouter Swierstra ([http://twitter.com/wouterswierstra wouterswierstra])<br />
* Tristan Allwood ([http://twitter.com/TotallyToRA TotallyToRA])<br />
* Benedict Eastaugh ([http://twitter.com/extralogical extralogical])<br />
* Alex Mason ([http://twitter.com/axman66 Axman6])<br />
* John Van Enk ([http://twitter.com/sw17ch sw17ch])<br />
* Robin Green ([http://twitter.com/greenrd greenrd])<br />
* Nicolas Pouillard ([http://twitter.com/npouillard npouillard])<br />
* Joe Fredette ([http://twitter.com/jfredett jfredett])<br />
* Jason Dusek ([http://twitter.com/solidsnack solidsnack])<br />
<br />
'''Haskell companies on Twitter'''<br />
<br />
* Galois ([http://twitter.com/galoisinc galoisinc])<br />
* Tupil ([http://twitter.com/tupil tupil])<br />
<br />
'''Haskell buzz on Twitter'''<br />
<br />
* [http://twitter.com/paytonrules/statuses/946501437 Officially amazed at the Haskell chat room. I asked a simple question there, and they went nuts on it. In a good way.]<br />
* [http://twitter.com/lallysingh/statuses/945333684 Haskell has interactive plotting commands for charts/graphs/etc. That's it, I'm officially in love]<br />
* [http://twitter.com/gimboland/statuses/944893593 God, I love Haskell]<br />
* [http://twitter.com/tsmosca/statuses/943950292 Ease of Haskell vs. Java: amazing!]<br />
* [http://twitter.com/arnax/statuses/943659297 The joy of opening a mind to Haskell :-)]<br />
* [http://twitter.com/mattpodwysocki/statuses/942618649 Aw, sweet, building a MP3 decoder in Haskell. Geek explosion ensues]<br />
* [http://twitter.com/rbp/statuses/942546816 You know, haskell actually pretty much rules :)]<br />
* [http://twitter.com/pavan_mishra/statuses/941707547 Awed by Haskell]<br />
* [http://twitter.com/clehene/statuses/939600495 I can haskell from iPhone with hugs98]<br />
<br />
[[Category:Community]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Maintaining_laziness&diff=25361Maintaining laziness2008-12-31T05:21:43Z<p>Jsnx: </p>
<hr />
<div>One of Haskell's main features is [[non-strict semantics]], which in is implemented by [[lazy evaluation]] in all popular Haskell compilers.<br />
However many Haskell libraries found on [[Hackage]] are implemented just as if Haskell would be a strict language.<br />
This leads to unnecessary inefficiencies, [[memory leak]]s and, we suspect, unintended semantics.<br />
In this article we want to go through some techniques on how to check lazy behaviour on functions,<br />
examples of typical constructs which break laziness without need,<br />
and finally we want to link to techniques that may yield the same effect without laziness.<br />
<br />
== Checking laziness ==<br />
<br />
If you want to check whether a function is lazy enough, you may feed it with undefined values.<br />
An undefined value can be <hask>undefined</hask>, <hask>error "reason"</hask>, or an infinite loop.<br />
The latter one has the advantage that it cannot be hidden by some hacks like "catching" the error in the IO monad.<br />
<br />
Examples:<br />
Check whether <hask>filter</hask> is lazy:<br />
<haskell><br />
filter even [0..]<br />
filter even ([0..5] ++ undefined)<br />
</haskell><br />
If the <hask>filter</hask> function is lazy<br />
then it keeps generating elements in the first case<br />
and it outputs a prefix of the output list, before breaking because of the undefined, in the second case.<br />
<br />
An automated unit test can check whether infinite or corrupted input data produces correct prefixes.<br />
Those tests usually do not fail by returning <hask>False</hask> but by leading to undefined results,<br />
either explicit <hask>undefined</hask> or an infinite loop.<br />
<haskell><br />
testFilter0 = filter even [0..100] `isPrefixOf` filter even [0..]<br />
testFilter1 = filter even [0..100] `isPrefixOf` filter even ([0..102]++undefined)<br />
testFilter2 = let x = filter even [0..] !! 100 in x==x<br />
testFilter3 = let x = filter even ([0..102]++undefined) !! 50 in x==x<br />
</haskell><br />
<br />
<br />
== Laziness breakers ==<br />
<br />
=== Maybe, Either, Exceptions ===<br />
<br />
Some laziness breakers are visible in type signatures:<br />
<haskell><br />
decodeUTF8 :: [Word8] -> Either Message String<br />
</haskell><br />
The <hask>Either</hask> type signals that the function marks decoding failure by using the <hask>Left</hask> constructor of <hask>Either</hask>.<br />
This function cannot be lazy, because when you access the first character of the result,<br />
it must already be computed, whether the result is <hask>Left</hask> or <hask>Right</hask>.<br />
For this decision, the complete input must be decoded.<br />
A better type signature is<br />
<haskell><br />
decodeUTF8 :: [Word8] -> (Maybe Message, String)<br />
</haskell><br />
where the <hask>String</hask> contains as much characters as could be decoded<br />
and <hask>Maybe Message</hask> gives the reason for the stop of the decoding.<br />
<hask>Nothing</hask> means the input was completely read,<br />
<hask>Just msg</hask> means the decoding was aborted for the reason described in <hask>msg</hask>.<br />
If you touch the first element of the pair, the complete decodings is triggered, thus laziness is broken.<br />
This means you should first process the <hask>String</hask> and look at <hask>Maybe Message</hask> afterwards.<br />
<br />
Instead of the unspecific pair type you should use the special type for asynchronous exceptions as found in the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/explicit-exception explicit exception] package.<br />
<br />
<br />
Especially in parsers you may find a function, called Wadler's force function.<br />
It works as follows:<br />
<haskell><br />
force y =<br />
let Just x = y<br />
in Just x<br />
</haskell><br />
It looks like a complicated expression for <hask>y</hask><br />
with an added danger of failing unrecoverably when <hask>y</hask> is not <hask>Just</hask>.<br />
Its purpose is to use the lazy pattern matching of <hask>let</hask><br />
and to show to the runtime system, that we expect that <hask>y</hask> is always a <hask>Just</hask>.<br />
Then the runtime system need not to wait until it can determine the right constructor but it can proceed immediately.<br />
This way a function can be made lazy, also if it returns <hask>Maybe</hask>.<br />
It can however fail, if later it turns out, that <hask>y</hask> is actually <hask>Nothing</hask>. <!-- fail how? To be lazy? Or it is some hideous failure like 'head []'? --><br />
<br />
Using force like functions is sometimes necessary,<br />
but should be avoided for data types with more than one constructor.<br />
It is better to use an interim data type with one constructor and lift to the multi-constructor datatype when needed.<br />
Consider parsers of type <hask>StateT [Word8] Maybe a</hask>.<br />
Now consider the parser combinator <haskell>many :: StateT [Word8] Maybe a -> StateT [Word8] Maybe [a]</haskell><br />
which parses as many elements of type <hask>a</hask> as possible.<br />
It shall be lazy and thus must be infallible and must not use the <hask>Maybe</hask>.<br />
It shall just return an empty list, if parsing of one element fails.<br />
A quick hack would be to define <hask>many</hask> using a <hask>force</hask> function.<br />
It would be better to show by the type, that <hask>many</hask> cannot fail:<br />
<haskell>many :: StateT [Word8] Maybe a -> StateT [Word8] Identity [a]</haskell>.<br />
<br />
=== Early decision ===<br />
<br />
==== List construction ====<br />
<br />
Be aware that the following two expression are not equivalent.<br />
<haskell><br />
-- less lazy<br />
if b then f x else f y<br />
-- more lazy<br />
f (if b then x else y)<br />
</haskell><br />
It is <hask>if undefined then f x else f y</hask> is <hask>undefined</hask>,<br />
whereas <hask>f (if b then x else y)</hask> is <hask>f undefined</hask>,<br />
which is a difference in [[non-strict semantics]].<br />
Consider e.g. <hask>if b then 'a':x else 'a':y</hask>.<br />
<br />
It is common source of too much strictness to make decisions too early and thus duplicate code in the decision branches.<br />
Intuitively spoken, the bad thing about [[code duplication]] (stylistic questions put aside) is,<br />
that the run-time system cannot see that in the branches some things are equal and do it in common before the critical decision.<br />
Actually, the compiler and run-time system could be "improved" to do so, but in order to keep things predictable, they do not do so.<br />
Even more, this behaviour is required by theory,<br />
since by pushing decisions to the inner of an expression you change the semantics of the expression.<br />
So we return to the question, what the programmer actually wants.<br />
<br />
Now, do you think this expression<br />
<haskell><br />
if b<br />
then [x]<br />
else y:ys<br />
</haskell><br />
is maximally lazy?<br />
It seems so, but actually it is not. In both branches we create non-empty lists, but the run-time system cannot see this.<br />
It is <hask>null (if undefined then [x] else y:ys)</hask> again <hask>undefined</hask>,<br />
but we like to have it evaluated to <hask>False</hask>.<br />
Here we need lazy pattern matching as provided by <hask>let</hask>.<br />
<haskell><br />
let z:zs =<br />
if b<br />
then [x]<br />
else y:ys<br />
in z:zs<br />
</haskell><br />
This expression always returns the constructor <hask>(:)</hask> and thus <hask>null</hask> knows that the list is not empty.<br />
However, this is a little bit unsafe, because the <hask>let z:zs</hask> may fail if in the branches of <hask>if</hask> there is an empty list.<br />
This error can only caught at run-time which is bad.<br />
We can avoid it using the single constructor pair type.<br />
<haskell><br />
let (z,zs) =<br />
if b<br />
then (x,[])<br />
else (y,ys)<br />
in z:zs<br />
</haskell><br />
which can be abbreviated to<br />
<haskell><br />
uncurry (:) (if b then (x,[]) else (y,ys))<br />
</haskell><br />
<br />
<br />
Another example is the <hask>inits</hask> function.<br />
In the Haskell 98 report the implementation<br />
<haskell><br />
inits :: [a] -> [[a]]<br />
inits [] = [[]]<br />
inits (x:xs) = [[]] ++ map (x:) (inits xs)<br />
</haskell><br />
is suggested.<br />
However you find that <hask>inits undefined</hask> is undefined,<br />
although <hask>inits</hask> always should return the empty list as first element.<br />
The following implementation does exactly this:<br />
<haskell><br />
inits :: [a] -> [[a]]<br />
inits xt =<br />
[] :<br />
case xt of<br />
[] -> []<br />
x:xs -> map (x:) (inits xs)<br />
</haskell><br />
See also the article on [[base cases and identities]].<br />
<br />
<br />
==== Reader-Writer-State monad ====<br />
<br />
I do not know whether the following example can be simplified.<br />
In this form it occured in a real application, namely the HTTP package.<br />
<br />
Consider the following action of the <hask>Control.Monad.RWS</hask> which fetches a certain number of elements from a list.<br />
The state of the monad is the input list we fetch the elements from.<br />
The reader part provides an element which means that the input is consumed.<br />
It is returned as singleton when the caller tries to read from a completely read input.<br />
The writer allows to log some information, however the considered action does not output something to the log.<br />
<haskell><br />
getN :: Int -> RWS a [Int] [a] [a]<br />
getN n =<br />
do input <- get<br />
if null input<br />
then asks (:[])<br />
else let (fetched,rest) = splitAt n input<br />
in put rest >> return fetched<br />
</haskell><br />
As we learned as good imperative programmers, we only call <hask>splitAt</hask> when the input is non-empty,<br />
that is, only if there is something to fetch.<br />
This works even more many corner cases, but not in the following one.<br />
Although <hask>getN</hask> does obviously not log something (i.e. it does not call <hask>tell</hask>),<br />
it requires to read the input in order to find out, that nothing was logged:<br />
<haskell><br />
*Test> (\(_a,_s,w) -> w) $ runRWS (getN 5) '\n' undefined<br />
*** Exception: Prelude.undefined<br />
</haskell><br />
<br />
The problem is again, that <hask>if</hask> checks the emptiness of the input,<br />
which is undefined, since the input is undefined.<br />
Thus we must ensure, that the invoked monadic actions are run independent from the input.<br />
Only this way, the run-time system can see that the logging stream is never touched.<br />
We start refactoring by calling <hask>put</hask> independently from <hask>input</hask>'s content.<br />
It works as well for empty lists, since <hask>splitAt</hask> will just return empty lists in this case.<br />
<haskell><br />
getN :: Int -> RWS a [Int] [a] [a]<br />
getN n =<br />
do input <- get<br />
let (fetched,rest) = splitAt n input<br />
put rest<br />
if null input<br />
then asks (:[])<br />
else return fetched<br />
</haskell><br />
This doesn't resolve the problem. There is still a choice between <hask>asks</hask> and <hask>return</hask>.<br />
We have to pull out <hask>ask</hask> as well.<br />
<haskell><br />
getN :: Int -> RWS a [Int] [a] [a]<br />
getN n =<br />
do input <- get<br />
let (fetched,rest) = splitAt n input<br />
put rest<br />
endOfInput <- ask<br />
return $<br />
if null input<br />
then [endOfInput]<br />
else fetched<br />
</haskell><br />
Now things work as expected:<br />
<haskell><br />
*Test> (\(_a,_s,w) -> w) $ runRWS (getN 5) '\n' undefined<br />
[]<br />
</haskell><br />
We learn from this example, that sometimes in Haskell it is more efficient to call functions that are not needed under some circumstances.<br />
Always remind, that the [[Do notation considered harmful|do notation]] looks only imperative, but it is not imperative.<br />
E.g., <hask>endOfInput</hask> is only evaluated if the end of the input is really reached.<br />
Thus, the call <hask>ask</hask> does not mean that there is actually an action performed between <hask>put</hask> and <hask>return</hask>.<br />
<br />
<br />
=== Strict pattern matching in a recursion ===<br />
<br />
Consider the <hask>partition</hask> function which sorts elements, that match a predicate, into one list and the non-matching elements into another list.<br />
This function should also work on infinite lists,<br />
but the implementation shipped with GHC up to 6.2 [http://www.haskell.org/pipermail/libraries/2004-October/002645.html failed on infinite lists].<br />
What happened?<br />
<br />
The reason was too strict pattern matching.<br />
<br />
Let's first consider the following correct implementation:<br />
<haskell><br />
partition :: (a -> Bool) -> [a] -> ([a], [a])<br />
partition p =<br />
foldr<br />
(\x ~(y,z) -><br />
if p x<br />
then (x : y, z)<br />
else (y, x : z))<br />
([],[])<br />
</haskell><br />
The usage of <hask>foldr</hask> seems to be reserved for advanced programmers.<br />
Formally <hask>foldr</hask> runs from the end to the start of the list.<br />
However, how can this work if there is a list without an end?<br />
That can be seen when applying the definition of <hask>foldr</hask>.<br />
<haskell><br />
foldr :: (a -> b -> b) -> b -> [a] -> b<br />
foldr _ b [] = b<br />
foldr f b (a:as) = f a (foldr f b as)<br />
</haskell><br />
Now we expand this once for an infinite input list, we get<br />
<haskell><br />
partition p (a:as) =<br />
(\ ~(y,z) -> if p a then (a:y, z) else (y, a:z)) (foldr ... ([],[]) as)<br />
</haskell><br />
We see that the whether <hask>a</hask> is prepended to the first or the second list,<br />
does only depend on <hask>p a</hask>, and neither on <hask>y</hask> nor on <hask>z</hask>.<br />
The laziness annotation <hask>~</hask> is crucial, since it tells, intuitively spoken,<br />
that we can rely on the recursive call of <hask>foldr</hask> to return a pair and not <hask>undefined</hask>.<br />
Omitting it, would require the evaluation of the whole input list before the first output element can be determined.<br />
This fails for infinite lists and is inefficient for finite lists, and that was the bug in former implementations of <hask>partition</hask>.<br />
Btw. by the expansion you also see, that it would not help to omit the tilde and apply the above 'force' trick to the 'if-then-else' expression.<br />
<br />
=== List reversal ===<br />
<br />
Any use of the list function <hask>reverse</hask> should alert you,<br />
since when you access the first element of a reversed list, then all nodes of the input list must be evaluated and stored in memory.<br />
Think twice whether it is really needed.<br />
The article [[Infinity and efficiency]] shows how to avoid list reversal.<br />
<br />
== Alternatives ==<br />
<br />
From the above issues you see that laziness is a fragile thing.<br />
Make one mistake and a function, carefully developed with laziness in mind, is no longer lazy.<br />
The type system will rarely help you hunting laziness breakers, and there is little support by debuggers.<br />
<br />
Thus detecting laziness breakers will often requires understanding of a large portion of code, which is against the idea of modularity, and knowledge about low-level details of compilation or the runtime system.<br />
<br />
Maybe for your case you will prefer a different idiom, that achieves the same goals in a safer way. See e.g. the [[Enumerator and iteratee]] pattern.<br />
<br />
[[Category:Idioms]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Haskell_logos/New_logo_ideas&diff=25187Haskell logos/New logo ideas2008-12-23T21:18:37Z<p>Jsnx: attribution</p>
<hr />
<div>'''The great 2009 Haskell logo contest'''<br />
<br />
The Haskell logo has [http://www.willamette.edu/~fruehr/logos/intro.html changed over time], and the current "new" logo reflects the<br />
advanced features of Haskell. However, it is looking rather dated, and doesn't necessarily reflect the mature Haskell we have now.<br />
<br />
So, time to find a new logo. Something reflecting the modern emphasis of<br />
Haskell on purity and simplicity.<br />
<br />
Please submit logo-sized (not overly large) versions of your logo with optional text, with a preferably white background (such as for use on haskell.org).<br />
<br />
Please submit your entries here, and attach your name to them please. To be eligible,<br />
they will need to be visible on this page (e.g. uploaded, or link to the image). The image should be freely available (a suitable freely distributable license). Entries not displayed here won't be eligible.<br />
<br />
''The deadline for submissions is December 31, 2008, after which the top few submissions will be voted on by the community to decide a winner!''<br />
<br />
<br />
''' Adjectives '''<br />
<br />
<br />
A logo is part of a brand, and a brand is used to project an image. Therefore an important part of this exercise is deciding what image we want to project. An image can be described using a list of adjectives. So here is a sample of adjectives that we might want. This list is not exhaustive: by all means add more if you want them.<br />
<br />
''abstract, academic, accessible, accurate, adventurous, business-like, communal, complicated, dangerous, different, easy, exciting, familiar, friendly, fun, fuzzy, hard, interesting, inventive, precise, productive, profitable, reliable, revolutionary, safe, simple, strange, supportive, warm, welcoming.''<br />
<br />
I suggest that entries are accompanied by the two or three adjectives they are trying to project. [[User:PaulJohnson|PaulJohnson]]<br />
<br />
----<br />
<br />
This ASCII logo connects Haskell to LOLz, for pure win.<br />
<br />
<pre><br />
we<br />
did<br />
it for<br />
the λulz<br />
</pre><br />
<br />
[[User:Jsnx|jsnx]] 21:18, 23 December 2008 (UTC)<br />
<br />
----<br />
<br />
Logo with a leopard in the shape of a lambda. This one is traced from a bitmap, so it doesn't look brilliant. Should this one be chosen a better one can be drawn.<br />
<br />
[[Image:Haskell_logo_ideas_7_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 07:11, 22 December 2008 (UTC)<br />
<br />
----<br />
[[Image:lambdanimal.png|150px]]<br />
[[Image:lambdanimal_nomane.png|150px]]<br />
<br />
Strange Lambdanimal, with or without a mane. [[Media:lambdanimal.svg|SVG (inkscape)]].<br />
<br />
by [[User:Ripounet|Ripounet]] 22:24, 18 December 2008 (UTC)<br />
<br />
----<br />
[http://galois.com/~dons/images/logos/Haskell_logo.png http://galois.com/~dons/images/logos/Haskell_logo.png]<br />
<br />
Dana Herz @ Galois.<br />
<br />
----<br />
[[Image:Haskell-tao.png|Haskell as Taoism]]<br />
<br />
Playing off a recent Haskell-Cafe thread, in which programming languages were compared to religions, and Haskell was equated to Taoism. The slogan makes at least a ''little'' sense: it obviously goes with the logo, and 'Duals' are important to Cat theory, which influences Haskell strongly. [[Media:Haskell-tao.svg|SVG]] available. Font is Lucida Calligraphic, a less ubiquitous calligraphic font might be better.<br />
<br />
--[[User:Rgreayer|Rgreayer]] 15:16, 18 December 2008 (UTC)<br />
----<br />
[[Image:unsafeHaskell.png]]<br />
[[User:Beelsebob|Beelsebob]] 09:09, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:haskell-cjay2.png]]<br />
[[User:Cjay|cjay]] 03:49, 18 December 2008 (UTC)<br />
<br />
<br />
[[Image:haskell-cjay2a.png]]<br />
[[User:Cjay|cjay]] 14:27, 18 December 2008 (UTC)<br />
<br />
<br />
[[Image:haskell-cjay2b.png]]<br />
[[User:Cjay|cjay]] 03:22, 19 December 2008 (UTC)<br />
<br />
<br />
[[Image:haskell-cjay2c.png]]<br />
[[User:Cjay|cjay]] 23:03, 19 December 2008 (UTC)<br />
<br />
<br />
Available as svg [[Media:Haskell-cjay2.svg|1]] [[Media:Haskell-cjay2a.svg|2]] [[Media:Haskell-cjay2b.svg|3]] [[Media:Haskell-cjay2c.svg|4]] (inkscape). Fonts: FreeSerif for lambda, >> and the arrow head; Impact Label for "Haskell" (1&2), SF Alien Encounters Solid (3) (all free).<br />
<br />
----<br />
<br />
My attempt at a new Haskell logo:<br />
<br />
[[Image:Haskell_jdr.png]]<br />
<br />
So I guess the standalone version would then be:<br />
<br />
[[Image:Haskell_h_jdr.png]]<br />
<br />
[http://www.voetsjoeba.com Jeroen De Ridder]<br />
<br />
----<br />
<br />
[http://galois.com/~dons/images/logo-3-curved.png http://galois.com/~dons/images/logo-3-curved.png]<br />
<br />
[http://article.gmane.org/gmane.comp.lang.haskell.cafe/49072 George Pollard]<br />
<br />
----<br />
<br />
[[Image:Jeff-heard-1.png]]<br />
<br />
[http://thread.gmane.org/gmane.comp.lang.haskell.cafe/48892/focus=48893 Jeff Heard]. <br />
<br />
----<br />
<br />
Here's an attempt to depict the polish, elegance, and purity of Haskell by merging the H and lambda into an iconic gem.<br />
<br />
[[Image:Haskell2v3.png]]<br />
<br />
Made in Inkscape, with an SVG available.<br />
<br />
--[[User:Chromakode|Chromakode]] 03:18, 17 December 2008 (UTC)<br />
<br />
:I love that one, hope it wins. But I can't see the lambda merged in it, where is it hidden? [[User:Ripounet|Ripounet]]<br />
<br />
:Thanks for your comment. :)<br />
:The light blue highlight of the H is in the shape of an abstract lambda. [[User:Chromakode|Chromakode]]<br />
<br />
A variation of this logo where the H is made up of two lambdas:<br />
<br />
[[Image:Haskell_logo_ideas_6_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 00:30, 22 December 2008 (UTC)<br />
<br />
----<br />
<br />
All credit goes to Darrin Thompson for posting the ASCII inspiration for this to haskell-cafe. I, Jeff Wheeler, just mocked it up to look<br />
pretty. Here are two interpretations:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo1.png http://media.nokrev.com/junk/haskell-logos/logo1.png]<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo2.png http://media.nokrev.com/junk/haskell-logos/logo2.png]<br />
<br />
Two with rounded edges:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo8.png http://media.nokrev.com/junk/haskell-logos/logo8.png]<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo9.png http://media.nokrev.com/junk/haskell-logos/logo9.png]<br />
<br />
Here's a icon-sized version:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo4.png http://media.nokrev.com/junk/haskell-logos/logo4.png]<br />
<br />
The first two without an background:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo6.png http://media.nokrev.com/junk/haskell-logos/logo6.png] [http://media.nokrev.com/junk/haskell-logos/logo7.png http://media.nokrev.com/junk/haskell-logos/logo7.png]<br />
<br />
--[[User:Jeffwheeler|Jeffwheeler]] 02:42, 17 December 2008 (UTC)<br />
----<br />
Mix and match<br />
<br />
[http://relapse-software.net/haskell_7.png http://relapse-software.net/haskell_7.png]<br />
<br />
[[User:NHA|NHA]]<br />
----<br />
More mix and match, borrowing bind-lambda icon, star/flower idea, and font/verbiage from other submissions...(Raspoutine Classic font, [[Media:Haskell-Symstar.svg|SVG]] available).<br />
[[Image:Haskell-Symstar.png|Haskell - Logo variant]]<br />
<br />
--[[User:Rgreayer|Rgreayer]] 21:39, 17 December 2008 (UTC)<br />
----<br />
I really like the logo above. Here are some variations. The font name is ModeNine.<br />
<br />
<br />
[[Image:Haskellvariations1.jpg|Haskell - Logo Variations A]]<br />
<br />
[[Image:Haskellvariations2.jpg|Haskell - Logo Variations B]]<br />
<br />
--[[User:Reified|Reified]] 14:48, 17 December 2008 (UTC)<br />
<br />
----<br />
<br />
A different logo idea, using toddler's letter blocks to convey the simplicity of Haskell. Exact block look and font used can be changed,<br />
but this is the basic idea.<br />
<br />
[[Image:Haskell_logo_ideas_4_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 23:29, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Stupidb123logo.jpg]]<br />
<br />
--[[User:Stupidb123|Stupidb123]] 12:40, 16 December 2008 (UTC)<br />
<br />
----<br />
"The lightbulb lady" (concept: a lady/lightbulb made out of an inverted lambda, hope it catches...).<br />
Font: Museo Sans 500 (free of charge, add to the cart [http://new.myfonts.com/fonts/exljbris/museo-sans/500/ here]).<br />
<br />
[[Image:The_lady.png]]<br />
<br />
-- [[User:eu-prleu-peupeu]]<br />
----<br />
Just another version of the initial spreadshirt variant. <br />
The black background is now part of the logo. The text should be optional.<br />
<br />
[[Image:haskell_spreadshirt_logo.png|400px]]<br />
<br />
[[User:Frosch03|Frosch03]] 11:41, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
Made with Inkscape. The source in SVG is available [http://www.gburri.org/bordel/logo_haskell_gburri.svg here]. Font : [http://www.dafont.com/raspoutine.font?nb_ppp=50&text=Haskell Raspoutine (free)].<br />
<br />
The idea is to hide a lambda into an elegant and colored logo.<br />
<br />
Adjectives : ''elegant'', ''fun'', ''simple''<br />
<br />
[[Image:haskel_logo_preview_gburri.png]]<br />
<br />
[[User:Gburri|Gburri]] 09:58, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
Lambdas in a circle, forming a flower. I wanted it to be easy to draw, be subtle and look nice for haskellers and non-haskellers alike. Created in inkscape using free fonts.<br />
<br />
[[Image:Haskell-flower3.png]]<br />
<br />
--[[User:Tanimoto|tanimoto]] 05:39, 19 December 2008 (UTC)<br />
<br />
----<br />
<br />
A different take on the lambda-in-a-circle logo that looks less like the Half Life logo. Probably fits better than the monadic sequence<br />
operator in my other submission.<br />
<br />
[[Image:Haskell_logo_ideas_2_falconnl.png]]<br />
<br />
Update:<br />
Slight change and added letters, this time in the free Fonce Sans [http://liquisoft.deviantart.com/art/Fonce-Sans-Regular-Trial-25092730]<br />
font. I like Officina better, but if the font has to be free this is a reasonable substitute.<br />
<br />
[[Image:Haskell_logo_idea_3_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 08:34, 16 December 2008 (GMT +1)<br />
<br />
----<br />
<br />
Very quick attempt:<br />
<br />
[[Image:BurkeLibbey_Haskell.png]]<br />
<br />
The main font is [http://www.josbuivenga.demon.nl/diavlo.html Diavlo] (free). The lambda is in Candara, which I believe ships with Vista<br />
and/or XP. Not sure of the licensing there. If there's significant interest in this, I'll redo it as a vector graphic.<br />
<br />
-- [[User:Burke|Burke]] 02:33, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
On behalf of the Ministry of Safety and Happiness I would like to promote the meme suggesting that Haskell is the programming language of<br />
choice for the Illuminati.<br />
<br />
[[Image:Haskell proceed.png]]<br />
<br />
--[[User:CznpyHrnjwczky|CznpyHrnjwczky]] 05:31, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
More of a mascotte, though she could be used in a logo as well.<br />
<br />
This is Monica Monad, and she's a Warm Fuzzy Thing. Just giving a face to SPJ's alternative name for monads :)<br />
<br />
Her main purpose would be to present tutorials.<br />
<br />
[[Image:Monica_monad_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 00:52, 16 December 2008 (GMT +1)<br />
<br />
----<br />
<br />
A slightly different take on the Haskell logo, as the lambda-in-a-circle looks a bit too much like the Half Life logo for my taste. This<br />
one references monads instead of lambda calculus. Three possible slogans, emphasizing the fun that comes from programming in Haskell.<br />
Number 2 and 3 also reference function composition. Number 3 is my personal favourite.<br />
<br />
[[Image:Haskell_logo_ideas_falconnl.png]]<br />
<br />
Update: a combination of my two logos on a t-shirt. This time with function arrows to indicate the causal relationships: because Haskell is<br />
pure, it's simple. Because it's simple, it's fun.<br />
<br />
[[Image:Haskell_logo_ideas_tshirt_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 22:58, 15 December 2008 (GMT +1)<br />
<br />
: Yummy. What's the font? Is it free? [[User:Porges|Porges]] 21:59, 15 December 2008 (UTC)<br />
: Unfortunately, no. The font is called Officina Sans. Is that a problem? [[User:FalconNL|FalconNL]] 00:02, 16 December 2008 (GMT +1)<br />
<br />
: I like this t-shirt a lot, but I'd change 2 things: change "simple" to "lazy" (I think "pure -> lazy -> fun" is more provocative), and change the lambda to ">>" (there are too many languages with lambda logos already). When can I place my order? :-) --[[User:Warren|Warren]] 16:32, 23 December 2008 (UTC)<br />
<br />
----<br />
<br />
Simple, clean:<br />
<br />
[http://hpsg.fu-berlin.de/~rsling/img/haskell-shirt.jpeg http://hpsg.fu-berlin.de/~rsling/img/haskell-shirt.jpeg]<br />
<br />
I really like this t-shirt logo, by the way. Gets my vote so far. — [[User:Chrisdone|Chrisdone]] 00:18, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
Minor tweak to the above:<br />
<br />
[[Image:HaskellLogo-v2.png]]<br />
<br />
----<br />
<br />
Minor modification of the t-shirt logo, the lambda was a bit skewed in my opinion:<br />
<br />
[[Image:tshirt-logo-mod.png]]<br />
<br />
And another modification of the same theme:<br />
<br />
[[Image:tshirt-logo-mod-inv.png]]<br />
<br />
--[[User:Sebastiaan|Sebastiaan]] 13:29, 15 December 2008 (UTC)<br />
: I really like this one. A font other than Arial would be nice ;) [[User:Porges|Porges]] 21:25, 15 December 2008 (UTC)<br />
<br />
[[Image:HaskellLogoTShirtWhite.png]] -- [[User:Chrisdone|Chrisdone]] 23:19, 15 December 2008 (UTC)<br />
<br />
<br />
<br />
----<br />
<br />
Some ideas. Supposed to resemble a lambda abstraction. I realise there are no formal parameters. ---- [[User:Chrisdone|Chrisdone]] 00:12,<br />
15 December 2008 (UTC)<br />
<br />
[http://chrisdone.com/haskell-blah.png http://chrisdone.com/haskell-blah-thumb.png]<br />
<br />
----<br />
<br />
Here's another one; lambda is Gentium SIL, Haskell is MgOpen Cosmetica, tagline is MgOpen Canonica Italic. [[User:Porges|Porges]] 21:25, 15<br />
December 2008 (UTC)<br />
<br />
[[Image:Haskell Logo.png]]<br />
<br />
----<br />
<br />
Another take. A bit simpler, more symmetrical.<br />
<br />
[[Image:haskelllogobeshers.png]]<br />
<br />
----<br />
<br />
[[Image:Haskell-logo.png]]<br />
<br />
The logo uses Kautiva Bold as (non-free) font.<br />
<br />
--[[User:Eelco|Eelco]] 07:43, 15 December 2008 (UTC)<br />
<br />
This one is dedicated to Derek Elkins, to sooth his eyes after having them hurt on the previous logo:<br />
<br />
[[Image:Haskell-logo-funny.png]]<br />
<br />
--[[User:Eelco|Eelco]] 08:53, 15 December 2008 (UTC)<br />
: Makes sense. Comic Sans is the *Official Font of Haskell*, after all.<br />
<br />
----<br />
[[Image:HaskellLogoTDavie.png]]<br />
<br />
[[Image:HaskellLogoTDavie.pdf]] (vector pdf version)<br />
<br />
[[Image:HaskellLogoTDavie2.png]]<br />
<br />
[[User:Beelsebob|Beelsebob]] 08:32, 15 December 2008 (UTC)<br />
<br />
---- <br />
<br />
[http://relapse-software.net/haskell_0.png http://relapse-software.net/haskell_0.png]<br />
<br />
[http://relapse-software.net/haskell_1.png http://relapse-software.net/haskell_1.png]<br />
<br />
[http://relapse-software.net/haskell_2.png http://relapse-software.net/haskell_2.png]<br />
<br />
[http://relapse-software.net/haskell_3.png http://relapse-software.net/haskell_3.png]<br />
<br />
<br />
[http://relapse-software.net/hasksun4.png http://relapse-software.net/hasksun4.png]<br />
<br />
[http://relapse-software.net/hasksun6.png http://relapse-software.net/hasksun6.png]<br />
<br />
[[User:NHA|NHA]]<br />
----<br />
<br />
<br />
Logo fun using Blender:<br />
<br />
[[Image:HsLogosMB.png|center|Haskell Logo idea with lambda as mascot]]<br />
<br />
I tried to give the lambda sign an ''alive'' feeling. --[[User:GokhanSan|GokhanSan]] 12:49, 15 December 2008 (UTC)<br />
: Middle one looks a bit too much like the ghostbusters logo :D [[User:Porges|Porges]] 21:25, 15 December 2008 (UTC)<br />
:: Hmm, I wonder if it's the choice of colors. Then again, with a minor alteration, we get a FreeBSD icon candidate:<br />
[[Image:HsLogoMB-BSD.png|beastie]] ;-) --[[User:GokhanSan|GokhanSan]] 08:52, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:HaskellLogoIdea05.gif]]<br />
<br />
Not sure about the colour. I tried to pick the purple from the current logo. Although the lower lambda is rotated there is<br />
[http://poinikastas.csad.ox.ac.uk/browseGlyphs.shtml historic precedence] for other forms of the letter. The lambda takes the angle from<br />
the 'k'. Font is News Gothic. Feel free to play with the concept. [[User:Rk|Rk]] 11:13, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
<br />
More vectorial Haskell logo concepts. Using inkscape and the popular [http://inde-graphics.deviantart.com/art/advent-font-57338302 advent<br />
font] (CC at-nc-nd).<br />
<br />
[[Image:Haskell_infinitylambda.png]]<br />
[[Image:Haskell_halfhalfinfinitylambda.png]]<br />
[[Image:Haskell_3qhalfinfinitylambda.png]]<br />
<br />
Vectorial images (svg):<br />
<br />
[http://haskell.org/sitewiki/images/8/86/Haskell_infinitylambda.svg 1]<br />
[http://haskell.org/sitewiki/images/d/df/Haskell_halfinfinitylambda.svg 2]<br />
[http://haskell.org/sitewiki/images/6/66/Haskell_3qhalfinfinitylambda.svg 3]<br />
<br />
* [[User:alvivi|alvivi]] 19:28, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Haskell-pure.png|haskell::pure]]<br />
<br />
--[[User:Rgreayer|Rgreayer]] 20:44, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
Find a font where 'k' looks like a reverse lambda (after removing the "stalk"). For example:<br />
<br />
[[Image:Kaskell.png|Kaskell]]<br />
<br />
Note this example uses Monotype Corsiva which is not a free font. If the basic approach looks good, we can find a similar free font that<br />
works.<br />
<br />
--[[User:Orenbenkiki|OrenBenKiki]] 01:40, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[http://relapse-software.net/haskell_5.png http://relapse-software.net/haskell_5.png]<br />
<br />
----<br />
<br />
[[Image:Haskell.png|Haskellll]]<br />
<br />
Illustrator, vector art available, apologies to GokhanSan<br />
<br />
--[[User:Mpeter|Mpeter]] 10:18, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
<br />
[http://relapse-software.net/haskell_6.png http://relapse-software.net/haskell_6.png]<br />
<br />
----<br />
<br />
[[Image:Haskell3.png|Haskell]]<br />
[[Image:Haskell4.png|Haskell]]<br />
<br />
Inkscape, vector art available.<br />
<br />
--[[User:Chromakode|Chromakode]] 07:14, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
I'll probably regret this...<br />
<br />
[[Image:NarleyYeeaaahh.jpg|Haskell - Narwals, YEEAAAAHH!!]]<br />
<br />
(Created with PAINT.NET)<br />
<br />
--[[User:Reified|Reified]] 07:20, 16 December 2008 (UTC)<br />
:It's a fun one but I erroneously read " Chaskell YEEAAAHH!! " [[User:Ripounet|Ripounet]]<br />
----<br />
<br />
The general idea is that it's just "Haskell" but with w lambda instead of the a. The font here is Myriad Pro but this would work with any<br />
good sans-serif font. It's color-agnostic, so it can be easily printer, presented as white on black or changed to a different color.<br />
<br />
[[Image:Haskell_logo_bonus.png]]<br />
<br />
[[Image:Haskell_logo_bonus2.png]]<br />
<br />
--[[User:BONUS|BONUS]] 14:40, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Axman6-logo-1.0.png]]<br />
<br />
In black:<br />
<br />
[[Image:Axman6-logo-1.1.png]]<br />
<br />
[[Image:Axman6-logo-1.1-small.png]]<br />
<br />
--[[User:Axman6|Axman6]] 15:16, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Haskell_girl.jpg]]<br />
<br />
<br />
Oh, didn't know png's would work.<br />
--[[User:Tindrum|Tindrum]] 17:12, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Haskell_logo.png]]<br />
<br />
It is mutually recursive...<br />
Here is the [[Media:Haskell logo.svg|svg]].<br />
<br />
Second version:<br />
<br />
[[image:Haskell2_logo.png]]<br />
<br />
And the [[Media:Haskell2 logo.svg|svg]].<br />
<br />
--[[User:Trontonic|Trontonic]] 20:39, 16 December 2008 (UTC)<br />
<br />
----<br />
This is a variation on my [http://t-shirts.cafepress.com/item/lambda-revolution-fitted-tshirt/96543210 Cafepress t-shirt]. The PNG is<br />
generated from an Inkscape SVG.<br />
<br />
[[Image:Haskell-logo-revolution.png]]<br />
<br />
Adjectives: revolutionary<br />
<br />
[[User:PaulJohnson|PaulJohnson]] 21:08, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:haskell-cjay.png]]<br />
<br />
Available as [[Media:Haskell-cjay.svg|svg]] (inkscape). Fonts: FreeSerif for lambda and >>. Bitstream Vera and FreeMono for other (afaik<br />
all free to use)<br />
<br />
[[User:Cjay|cjay]] 22:45, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
http://conal.net/Pan/Gallery/haskell-powered%20on%20white%20tiled%20360.png<br />
<br />
One I made with [http://conal.net/Pan/Gallery Pan] (purely functional image synthesis in Haskell) some years back. See also the<br />
[http://conal.net/Pan/Gallery/haskell-powered%20on%20white%20tiled%20720.png 720 square version]. I have a few sizes up to 2250 pixels<br />
square.<br />
<br />
[[User:Conal|Conal]] 03:40, 17 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Haskell_lambda.png]]<br />
<br />
Just kidding :P<br />
<br />
--[[User:Trontonic|Trontonic]] 05:04, 17 December 2008 (UTC)<br />
<br />
----<br />
=== Cale Gibbard ===<br />
[[Image:Haskell-logo-6up.png]]<br />
<br />
[http://haskell.org/haskellwiki/Image:Haskell-logo-6up.svg Inkscape SVG]<br />
<br />
I originally had no specific mountain in mind, but Don Stewart pointed out that this might be representative of Mt. Hood in Portland, Oregon, where Haskell was named.<br />
<br />
Regardless, I thought a summit, bathed in the pure mountain air would be a decent symbol for Haskell, the peak of contemporary programming. :)<br />
<br />
[[User:CaleGibbard|CaleGibbard]] 05:55, 17 December 2008 (UTC)<br />
:Here's a modified version with a slightly funkier font :) I think that it matches the lines of the image better... [[User:Porges|Porges]] 03:14, 18 December 2008 (UTC)<br />
<br />
[[Image:Testhask.png]]<br />
----<br />
<br />
Probably not a good choice for a logo:<br />
<br />
[[Image:Hazard lambda cracked 2.png]]<br />
<br />
----<br />
<br />
[[Image:Haskell_Ribbons.png]]<br />
<br />
[http://slipgate.za.net/~korpse/misc/Haskell_Ribbons.svg SVG]<br />
<br />
Simplicity.<br />
<br />
(It is possible that the font may need to be replaced with a free alternative.)<br />
<br />
[[User:Jonathanj|JonathanJ]] 16:34, 17 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Haskelllogosmax.png]]<br />
<br />
Available as SVG.<br />
<br />
[[User:MaxRabkin|MaxRabkin]] 05:37, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:DoHaskell.png]]<br />
<br />
Another variation for the cognicenti:<br />
<br />
[[Image:JustHaskell.png]]<br />
<br />
--[[User:Warren|Warren]] 07:26, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
A slight variation of the ">\=" logo:<br />
<br />
[[Image:haskell-logo-doublef.png]]<br />
<br />
Not that it's worth much:). Available as [[Media:haskell-logo-doublef.svg|SVG]].<br />
<br />
[[User:Doublef|DoubleF]] 07:36, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:haskell-apankrat.png]]<br />
<br />
The idea for this [http://en.wikipedia.org/wiki/Wordmark_(graphic_identity) wordmark] is to modify ''A'' to resemble λ and through this tie together the "Haskell" to the "Lambda". Modified ''A'' also works well as a standalone logo:<br />
<br />
[[Image:haskell-symbol-apankrat.png]]<br />
<br />
Note that ''any'' logo based on the unmodified λ symbol may look ambiguous to the people outside of Haskell community. While the λ in the context of programming languages is clearly associated with functional programming, it ''is'' a lowercase Greek L and so it's reasonable for an outsider to associate it with '''L'''isp, and not Haskell.<br />
<br />
PS. I just scrolled up and saw BONUS'es entry (14:40, 16 December 2008). While its idea is close, I think using pure λ in place of an A doesn't work because it effectively turn the name into H-L-skell.<br />
<br />
[[User:Apankrat|Apankrat]] 07:38, 18 December 2008 (UTC)<br />
<br />
<br />
----<br />
A very simple logo, made with inkscape, using math fonts, with various grades (B&W, grays, fill color & gradient) and backgrounds<br />
[[Image:Simple_haskell.png]]<br />
<br />
SVG available here:<br />
[[Image:Simple haskell.svgz]]<br />
<br />
[[User:Aubanel|Aubanel]] 18:08, 18 December 2008 (UTC)<br />
<br />
<br />
<br />
----<br />
<br />
[[Image:g3634.png]]<br />
<br />
Available as Inkscape [[Media:dessin.svg|SVG]]<br />
<br />
[[Image:g4441.png]]<br />
<br />
Available as Inkscape [[Media:dessin2.svg|SVG]]<br />
<br />
[[User:runrun|runrun]] 18 December 2008<br />
<br />
----<br />
<br />
[[Image:Haskell-logo2-max.png]]<br />
<br />
Contact me for SVG. Font is not currently free, but I designed it, so this can change if it becomes "the Haskell font". I think it shows some of the elegance that Haskell has. If you like the font but can put it with a better logo, go ahead. --[[User:MaxRabkin|MaxRabkin]] 04:53, 19 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:sgf.png]]<br />
<br />
I think the best way to represent the pure, functional nature of Haskell is with a pure and functional logo! Something modernist, minimalist, clean and simple. I'd prefer not to put highlights of the language's syntax in the logo - that's remarkably concrete for a language good at abstraction. Even lambdas etc. should be slightly hidden - those who know what it's about can see them, and everyone else doesn't think 'what's that funny symbol?'. For the font, again, something functional like a light Helvetica or Univers.<br />
<br />
So, I thought I'd have a go at a few variations. I'm not convinced it's worked, but there you go. I've shamelessly ripped off tanimoto's idea. [[User:Sgf|Sgf]] 08:13, 19 December 2008 (UTC)<br />
<br />
* Sgf, I really like your logos and I think you captured my idea much better than I could do. I especially like the red one, a bit Escher-esque. I wonder if we could turn the blue one into something that looks more like a snowflake than it currently does. Thanks. [[User:Tanimoto|tanimoto]] 10:43, 19 December 2008 (UTC)<br />
<br />
* I also like the blue and the red logo. The resemblance of a snowflake fits the purity of the language. Perhaps you could give the lambda's more volume to make it more plate-like? [[User:Felix|Felix]]<br />
<br />
* Thanks for the comments. I'm going to be offline for about a week, so I'm not going to have a chance to knock up further variations soon, much as I would like to. So, if you have the time, feel free to generate variations from the [[Media:sgf.svg|Inkscape SVG]]. Otherwise, I'll have a go when I get back. Cheers, [[User:Sgf|Sgf]] 01:48, 20 December 2008 (UTC)<br />
<br />
[[Image:Sgf-logo-blue.png|Sgf-logo-blue]]<br />
<br />
Sgf's red logo changed to blue and with the Fonce Sans font that FalconNL has used for another logo. [[User:Felix|Felix]] 2008-12-21<br />
<br />
And another variation of Sgf's logo, this time using negative instead of positive space.<br />
<br />
[[Image:Haskell_logo_ideas_5_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 18:13, 21 December 2008 (UTC)<br />
<br />
----<br />
<br />
Yet another variation on tanimoto and sgf's themes, with influences from others. The intent here is fun, pure, simple, complete, intriguing, and a bit paradoxical. (The loose relation to the Cabal logo was unexpected.) Font is Free Sans, but I'd look for better if I had a bit more time.<br />
<br />
[[Image:Hs_logos_sereven.png]]<br />
<br />
The compiler sits at the core in negative space, its form suggested by what is built on and around it. Also in negative space, lambdas and reflected lambdas link the golden base library to others, pure primary colours available ready to be combined. Libraries become dimensional as they fit together like puzzle pieces. At each layer they form a whole, complete, yet extensible in all directions.<br />
<br />
[[User:sereven|sereven]] 12:24, 22 December 2008 (UTC)<br />
<br />
----<br />
λλλ<br />
<br />
Haskell The Revenge of the Nerds<br />
<br />
---<br />
<br />
[[Image:Ouroborous-oval.png|Ouroboros oval]]<br />
<br />
Paulo Tanimoto on the mailing list suggested something based on [http://www.example.com Orouboros]. Here is the [[Media:Ouroborous-oval.svg|Inkscape SVG]].<br />
<br />
Adjectives: abstract, friendly<br />
<br />
[[User:PaulJohnson|PaulJohnson]]<br />
<br />
----<br />
<br />
How about using one of the mythical birds in lambda calculus? Specifically, the ones from the article [http://users.bigpond.net.au/d.keenan/Lambda/ To Dissect a Mockingbird]. Some of the examples:<br />
<br />
http://users.bigpond.net.au/d.keenan/Lambda/Graphical_lambda2.gif (Mockingbird)<br />
<br />
http://users.bigpond.net.au/d.keenan/Lambda/Graphical_lambda6.gif (Omega bird)<br />
<br />
http://users.bigpond.net.au/d.keenan/Lambda/Graphical_lambda15.gif<br />
<br />
Since Haskell is centered around the idea of lambdas, I thought this would be a cool idea. Plus, they have qualities similar to Haskell: exotic, mysterious, abstract... [[User:Aviator|Aviator]] 12:35, 21 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Origami-lamdba-supernova-warp.png|The Haskell Origami Lambda's Warp from the Supernova]]<br />
This is an H composed of two identical vertically tiled lambdas warping from a supernova. It symbolizes the warp of the Haskell-lambda away from the O of object-orientation (symbolized by the supernova).<br />
<br />
Created in Inkscape, then adjusted in GIMP. This was my first try at using both tools. I have never done graphic design before.<br />
<br />
If I have time, I may submit a revised version.<br />
<br />
by [[User:DekuDekuplex|Benjamin L. Russell]] 22:17, 22 December 2008 (Tokyo Time)<br />
<br />
----<br />
<br />
[[Image:ClassyHLogo.png]]<br />
<br />
I created the current, apparently-much-loathed purple-and-green Haskell logo back in<br />
2004 at John Peterson's request. I actually sent him several designs, and I must admit <br />
I rather liked this one better, myself. I later included it on some of the<br />
CafePress merchandise as the "classy Haskell logo". It's main virtues are that it's <br />
sparse and abstract; it's specifically inspired by those hood ornaments you see on <br />
fancy cars (no relation to Andy Gill's Hood debugger).<br />
<br />
The fancy typeface goes a little against the grain of "sparse and abstract", but it's<br />
of course independent from the logo itself.<br />
<br />
The simplicity of the logo proper (modulo the shadow and the typeface) makes it easy to <br />
reproduce in SVG and the like.<br />
<br />
(For a brief time, this logo was available on CafePress in the form of a frisbee, er, <br />
"flying disc", but they stopped carrying the item. It has been available for a while <br />
on shirts and perhaps mugs as well.)<br />
<br />
Anyway, perhaps it will appeal to others over the current one as much as it did to me.<br />
<br />
by [[User:FritzRuehr|Fritz Ruehr]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Haskell_logos/New_logo_ideas&diff=25186Haskell logos/New logo ideas2008-12-23T21:17:36Z<p>Jsnx: LOLz</p>
<hr />
<div>'''The great 2009 Haskell logo contest'''<br />
<br />
The Haskell logo has [http://www.willamette.edu/~fruehr/logos/intro.html changed over time], and the current "new" logo reflects the<br />
advanced features of Haskell. However, it is looking rather dated, and doesn't necessarily reflect the mature Haskell we have now.<br />
<br />
So, time to find a new logo. Something reflecting the modern emphasis of<br />
Haskell on purity and simplicity.<br />
<br />
Please submit logo-sized (not overly large) versions of your logo with optional text, with a preferably white background (such as for use on haskell.org).<br />
<br />
Please submit your entries here, and attach your name to them please. To be eligible,<br />
they will need to be visible on this page (e.g. uploaded, or link to the image). The image should be freely available (a suitable freely distributable license). Entries not displayed here won't be eligible.<br />
<br />
''The deadline for submissions is December 31, 2008, after which the top few submissions will be voted on by the community to decide a winner!''<br />
<br />
<br />
''' Adjectives '''<br />
<br />
<br />
A logo is part of a brand, and a brand is used to project an image. Therefore an important part of this exercise is deciding what image we want to project. An image can be described using a list of adjectives. So here is a sample of adjectives that we might want. This list is not exhaustive: by all means add more if you want them.<br />
<br />
''abstract, academic, accessible, accurate, adventurous, business-like, communal, complicated, dangerous, different, easy, exciting, familiar, friendly, fun, fuzzy, hard, interesting, inventive, precise, productive, profitable, reliable, revolutionary, safe, simple, strange, supportive, warm, welcoming.''<br />
<br />
I suggest that entries are accompanied by the two or three adjectives they are trying to project. [[User:PaulJohnson|PaulJohnson]]<br />
<br />
----<br />
<br />
This ASCII logo connects Haskell to LOLz, for pure win.<br />
<br />
<pre><br />
we<br />
did<br />
it for<br />
the λulz<br />
</pre><br />
<br />
----<br />
<br />
Logo with a leopard in the shape of a lambda. This one is traced from a bitmap, so it doesn't look brilliant. Should this one be chosen a better one can be drawn.<br />
<br />
[[Image:Haskell_logo_ideas_7_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 07:11, 22 December 2008 (UTC)<br />
<br />
----<br />
[[Image:lambdanimal.png|150px]]<br />
[[Image:lambdanimal_nomane.png|150px]]<br />
<br />
Strange Lambdanimal, with or without a mane. [[Media:lambdanimal.svg|SVG (inkscape)]].<br />
<br />
by [[User:Ripounet|Ripounet]] 22:24, 18 December 2008 (UTC)<br />
<br />
----<br />
[http://galois.com/~dons/images/logos/Haskell_logo.png http://galois.com/~dons/images/logos/Haskell_logo.png]<br />
<br />
Dana Herz @ Galois.<br />
<br />
----<br />
[[Image:Haskell-tao.png|Haskell as Taoism]]<br />
<br />
Playing off a recent Haskell-Cafe thread, in which programming languages were compared to religions, and Haskell was equated to Taoism. The slogan makes at least a ''little'' sense: it obviously goes with the logo, and 'Duals' are important to Cat theory, which influences Haskell strongly. [[Media:Haskell-tao.svg|SVG]] available. Font is Lucida Calligraphic, a less ubiquitous calligraphic font might be better.<br />
<br />
--[[User:Rgreayer|Rgreayer]] 15:16, 18 December 2008 (UTC)<br />
----<br />
[[Image:unsafeHaskell.png]]<br />
[[User:Beelsebob|Beelsebob]] 09:09, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:haskell-cjay2.png]]<br />
[[User:Cjay|cjay]] 03:49, 18 December 2008 (UTC)<br />
<br />
<br />
[[Image:haskell-cjay2a.png]]<br />
[[User:Cjay|cjay]] 14:27, 18 December 2008 (UTC)<br />
<br />
<br />
[[Image:haskell-cjay2b.png]]<br />
[[User:Cjay|cjay]] 03:22, 19 December 2008 (UTC)<br />
<br />
<br />
[[Image:haskell-cjay2c.png]]<br />
[[User:Cjay|cjay]] 23:03, 19 December 2008 (UTC)<br />
<br />
<br />
Available as svg [[Media:Haskell-cjay2.svg|1]] [[Media:Haskell-cjay2a.svg|2]] [[Media:Haskell-cjay2b.svg|3]] [[Media:Haskell-cjay2c.svg|4]] (inkscape). Fonts: FreeSerif for lambda, >> and the arrow head; Impact Label for "Haskell" (1&2), SF Alien Encounters Solid (3) (all free).<br />
<br />
----<br />
<br />
My attempt at a new Haskell logo:<br />
<br />
[[Image:Haskell_jdr.png]]<br />
<br />
So I guess the standalone version would then be:<br />
<br />
[[Image:Haskell_h_jdr.png]]<br />
<br />
[http://www.voetsjoeba.com Jeroen De Ridder]<br />
<br />
----<br />
<br />
[http://galois.com/~dons/images/logo-3-curved.png http://galois.com/~dons/images/logo-3-curved.png]<br />
<br />
[http://article.gmane.org/gmane.comp.lang.haskell.cafe/49072 George Pollard]<br />
<br />
----<br />
<br />
[[Image:Jeff-heard-1.png]]<br />
<br />
[http://thread.gmane.org/gmane.comp.lang.haskell.cafe/48892/focus=48893 Jeff Heard]. <br />
<br />
----<br />
<br />
Here's an attempt to depict the polish, elegance, and purity of Haskell by merging the H and lambda into an iconic gem.<br />
<br />
[[Image:Haskell2v3.png]]<br />
<br />
Made in Inkscape, with an SVG available.<br />
<br />
--[[User:Chromakode|Chromakode]] 03:18, 17 December 2008 (UTC)<br />
<br />
:I love that one, hope it wins. But I can't see the lambda merged in it, where is it hidden? [[User:Ripounet|Ripounet]]<br />
<br />
:Thanks for your comment. :)<br />
:The light blue highlight of the H is in the shape of an abstract lambda. [[User:Chromakode|Chromakode]]<br />
<br />
A variation of this logo where the H is made up of two lambdas:<br />
<br />
[[Image:Haskell_logo_ideas_6_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 00:30, 22 December 2008 (UTC)<br />
<br />
----<br />
<br />
All credit goes to Darrin Thompson for posting the ASCII inspiration for this to haskell-cafe. I, Jeff Wheeler, just mocked it up to look<br />
pretty. Here are two interpretations:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo1.png http://media.nokrev.com/junk/haskell-logos/logo1.png]<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo2.png http://media.nokrev.com/junk/haskell-logos/logo2.png]<br />
<br />
Two with rounded edges:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo8.png http://media.nokrev.com/junk/haskell-logos/logo8.png]<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo9.png http://media.nokrev.com/junk/haskell-logos/logo9.png]<br />
<br />
Here's a icon-sized version:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo4.png http://media.nokrev.com/junk/haskell-logos/logo4.png]<br />
<br />
The first two without an background:<br />
<br />
[http://media.nokrev.com/junk/haskell-logos/logo6.png http://media.nokrev.com/junk/haskell-logos/logo6.png] [http://media.nokrev.com/junk/haskell-logos/logo7.png http://media.nokrev.com/junk/haskell-logos/logo7.png]<br />
<br />
--[[User:Jeffwheeler|Jeffwheeler]] 02:42, 17 December 2008 (UTC)<br />
----<br />
Mix and match<br />
<br />
[http://relapse-software.net/haskell_7.png http://relapse-software.net/haskell_7.png]<br />
<br />
[[User:NHA|NHA]]<br />
----<br />
More mix and match, borrowing bind-lambda icon, star/flower idea, and font/verbiage from other submissions...(Raspoutine Classic font, [[Media:Haskell-Symstar.svg|SVG]] available).<br />
[[Image:Haskell-Symstar.png|Haskell - Logo variant]]<br />
<br />
--[[User:Rgreayer|Rgreayer]] 21:39, 17 December 2008 (UTC)<br />
----<br />
I really like the logo above. Here are some variations. The font name is ModeNine.<br />
<br />
<br />
[[Image:Haskellvariations1.jpg|Haskell - Logo Variations A]]<br />
<br />
[[Image:Haskellvariations2.jpg|Haskell - Logo Variations B]]<br />
<br />
--[[User:Reified|Reified]] 14:48, 17 December 2008 (UTC)<br />
<br />
----<br />
<br />
A different logo idea, using toddler's letter blocks to convey the simplicity of Haskell. Exact block look and font used can be changed,<br />
but this is the basic idea.<br />
<br />
[[Image:Haskell_logo_ideas_4_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 23:29, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Stupidb123logo.jpg]]<br />
<br />
--[[User:Stupidb123|Stupidb123]] 12:40, 16 December 2008 (UTC)<br />
<br />
----<br />
"The lightbulb lady" (concept: a lady/lightbulb made out of an inverted lambda, hope it catches...).<br />
Font: Museo Sans 500 (free of charge, add to the cart [http://new.myfonts.com/fonts/exljbris/museo-sans/500/ here]).<br />
<br />
[[Image:The_lady.png]]<br />
<br />
-- [[User:eu-prleu-peupeu]]<br />
----<br />
Just another version of the initial spreadshirt variant. <br />
The black background is now part of the logo. The text should be optional.<br />
<br />
[[Image:haskell_spreadshirt_logo.png|400px]]<br />
<br />
[[User:Frosch03|Frosch03]] 11:41, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
Made with Inkscape. The source in SVG is available [http://www.gburri.org/bordel/logo_haskell_gburri.svg here]. Font : [http://www.dafont.com/raspoutine.font?nb_ppp=50&text=Haskell Raspoutine (free)].<br />
<br />
The idea is to hide a lambda into an elegant and colored logo.<br />
<br />
Adjectives : ''elegant'', ''fun'', ''simple''<br />
<br />
[[Image:haskel_logo_preview_gburri.png]]<br />
<br />
[[User:Gburri|Gburri]] 09:58, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
Lambdas in a circle, forming a flower. I wanted it to be easy to draw, be subtle and look nice for haskellers and non-haskellers alike. Created in inkscape using free fonts.<br />
<br />
[[Image:Haskell-flower3.png]]<br />
<br />
--[[User:Tanimoto|tanimoto]] 05:39, 19 December 2008 (UTC)<br />
<br />
----<br />
<br />
A different take on the lambda-in-a-circle logo that looks less like the Half Life logo. Probably fits better than the monadic sequence<br />
operator in my other submission.<br />
<br />
[[Image:Haskell_logo_ideas_2_falconnl.png]]<br />
<br />
Update:<br />
Slight change and added letters, this time in the free Fonce Sans [http://liquisoft.deviantart.com/art/Fonce-Sans-Regular-Trial-25092730]<br />
font. I like Officina better, but if the font has to be free this is a reasonable substitute.<br />
<br />
[[Image:Haskell_logo_idea_3_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 08:34, 16 December 2008 (GMT +1)<br />
<br />
----<br />
<br />
Very quick attempt:<br />
<br />
[[Image:BurkeLibbey_Haskell.png]]<br />
<br />
The main font is [http://www.josbuivenga.demon.nl/diavlo.html Diavlo] (free). The lambda is in Candara, which I believe ships with Vista<br />
and/or XP. Not sure of the licensing there. If there's significant interest in this, I'll redo it as a vector graphic.<br />
<br />
-- [[User:Burke|Burke]] 02:33, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
On behalf of the Ministry of Safety and Happiness I would like to promote the meme suggesting that Haskell is the programming language of<br />
choice for the Illuminati.<br />
<br />
[[Image:Haskell proceed.png]]<br />
<br />
--[[User:CznpyHrnjwczky|CznpyHrnjwczky]] 05:31, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
More of a mascotte, though she could be used in a logo as well.<br />
<br />
This is Monica Monad, and she's a Warm Fuzzy Thing. Just giving a face to SPJ's alternative name for monads :)<br />
<br />
Her main purpose would be to present tutorials.<br />
<br />
[[Image:Monica_monad_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 00:52, 16 December 2008 (GMT +1)<br />
<br />
----<br />
<br />
A slightly different take on the Haskell logo, as the lambda-in-a-circle looks a bit too much like the Half Life logo for my taste. This<br />
one references monads instead of lambda calculus. Three possible slogans, emphasizing the fun that comes from programming in Haskell.<br />
Number 2 and 3 also reference function composition. Number 3 is my personal favourite.<br />
<br />
[[Image:Haskell_logo_ideas_falconnl.png]]<br />
<br />
Update: a combination of my two logos on a t-shirt. This time with function arrows to indicate the causal relationships: because Haskell is<br />
pure, it's simple. Because it's simple, it's fun.<br />
<br />
[[Image:Haskell_logo_ideas_tshirt_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 22:58, 15 December 2008 (GMT +1)<br />
<br />
: Yummy. What's the font? Is it free? [[User:Porges|Porges]] 21:59, 15 December 2008 (UTC)<br />
: Unfortunately, no. The font is called Officina Sans. Is that a problem? [[User:FalconNL|FalconNL]] 00:02, 16 December 2008 (GMT +1)<br />
<br />
: I like this t-shirt a lot, but I'd change 2 things: change "simple" to "lazy" (I think "pure -> lazy -> fun" is more provocative), and change the lambda to ">>" (there are too many languages with lambda logos already). When can I place my order? :-) --[[User:Warren|Warren]] 16:32, 23 December 2008 (UTC)<br />
<br />
----<br />
<br />
Simple, clean:<br />
<br />
[http://hpsg.fu-berlin.de/~rsling/img/haskell-shirt.jpeg http://hpsg.fu-berlin.de/~rsling/img/haskell-shirt.jpeg]<br />
<br />
I really like this t-shirt logo, by the way. Gets my vote so far. — [[User:Chrisdone|Chrisdone]] 00:18, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
Minor tweak to the above:<br />
<br />
[[Image:HaskellLogo-v2.png]]<br />
<br />
----<br />
<br />
Minor modification of the t-shirt logo, the lambda was a bit skewed in my opinion:<br />
<br />
[[Image:tshirt-logo-mod.png]]<br />
<br />
And another modification of the same theme:<br />
<br />
[[Image:tshirt-logo-mod-inv.png]]<br />
<br />
--[[User:Sebastiaan|Sebastiaan]] 13:29, 15 December 2008 (UTC)<br />
: I really like this one. A font other than Arial would be nice ;) [[User:Porges|Porges]] 21:25, 15 December 2008 (UTC)<br />
<br />
[[Image:HaskellLogoTShirtWhite.png]] -- [[User:Chrisdone|Chrisdone]] 23:19, 15 December 2008 (UTC)<br />
<br />
<br />
<br />
----<br />
<br />
Some ideas. Supposed to resemble a lambda abstraction. I realise there are no formal parameters. ---- [[User:Chrisdone|Chrisdone]] 00:12,<br />
15 December 2008 (UTC)<br />
<br />
[http://chrisdone.com/haskell-blah.png http://chrisdone.com/haskell-blah-thumb.png]<br />
<br />
----<br />
<br />
Here's another one; lambda is Gentium SIL, Haskell is MgOpen Cosmetica, tagline is MgOpen Canonica Italic. [[User:Porges|Porges]] 21:25, 15<br />
December 2008 (UTC)<br />
<br />
[[Image:Haskell Logo.png]]<br />
<br />
----<br />
<br />
Another take. A bit simpler, more symmetrical.<br />
<br />
[[Image:haskelllogobeshers.png]]<br />
<br />
----<br />
<br />
[[Image:Haskell-logo.png]]<br />
<br />
The logo uses Kautiva Bold as (non-free) font.<br />
<br />
--[[User:Eelco|Eelco]] 07:43, 15 December 2008 (UTC)<br />
<br />
This one is dedicated to Derek Elkins, to sooth his eyes after having them hurt on the previous logo:<br />
<br />
[[Image:Haskell-logo-funny.png]]<br />
<br />
--[[User:Eelco|Eelco]] 08:53, 15 December 2008 (UTC)<br />
: Makes sense. Comic Sans is the *Official Font of Haskell*, after all.<br />
<br />
----<br />
[[Image:HaskellLogoTDavie.png]]<br />
<br />
[[Image:HaskellLogoTDavie.pdf]] (vector pdf version)<br />
<br />
[[Image:HaskellLogoTDavie2.png]]<br />
<br />
[[User:Beelsebob|Beelsebob]] 08:32, 15 December 2008 (UTC)<br />
<br />
---- <br />
<br />
[http://relapse-software.net/haskell_0.png http://relapse-software.net/haskell_0.png]<br />
<br />
[http://relapse-software.net/haskell_1.png http://relapse-software.net/haskell_1.png]<br />
<br />
[http://relapse-software.net/haskell_2.png http://relapse-software.net/haskell_2.png]<br />
<br />
[http://relapse-software.net/haskell_3.png http://relapse-software.net/haskell_3.png]<br />
<br />
<br />
[http://relapse-software.net/hasksun4.png http://relapse-software.net/hasksun4.png]<br />
<br />
[http://relapse-software.net/hasksun6.png http://relapse-software.net/hasksun6.png]<br />
<br />
[[User:NHA|NHA]]<br />
----<br />
<br />
<br />
Logo fun using Blender:<br />
<br />
[[Image:HsLogosMB.png|center|Haskell Logo idea with lambda as mascot]]<br />
<br />
I tried to give the lambda sign an ''alive'' feeling. --[[User:GokhanSan|GokhanSan]] 12:49, 15 December 2008 (UTC)<br />
: Middle one looks a bit too much like the ghostbusters logo :D [[User:Porges|Porges]] 21:25, 15 December 2008 (UTC)<br />
:: Hmm, I wonder if it's the choice of colors. Then again, with a minor alteration, we get a FreeBSD icon candidate:<br />
[[Image:HsLogoMB-BSD.png|beastie]] ;-) --[[User:GokhanSan|GokhanSan]] 08:52, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:HaskellLogoIdea05.gif]]<br />
<br />
Not sure about the colour. I tried to pick the purple from the current logo. Although the lower lambda is rotated there is<br />
[http://poinikastas.csad.ox.ac.uk/browseGlyphs.shtml historic precedence] for other forms of the letter. The lambda takes the angle from<br />
the 'k'. Font is News Gothic. Feel free to play with the concept. [[User:Rk|Rk]] 11:13, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
<br />
More vectorial Haskell logo concepts. Using inkscape and the popular [http://inde-graphics.deviantart.com/art/advent-font-57338302 advent<br />
font] (CC at-nc-nd).<br />
<br />
[[Image:Haskell_infinitylambda.png]]<br />
[[Image:Haskell_halfhalfinfinitylambda.png]]<br />
[[Image:Haskell_3qhalfinfinitylambda.png]]<br />
<br />
Vectorial images (svg):<br />
<br />
[http://haskell.org/sitewiki/images/8/86/Haskell_infinitylambda.svg 1]<br />
[http://haskell.org/sitewiki/images/d/df/Haskell_halfinfinitylambda.svg 2]<br />
[http://haskell.org/sitewiki/images/6/66/Haskell_3qhalfinfinitylambda.svg 3]<br />
<br />
* [[User:alvivi|alvivi]] 19:28, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Haskell-pure.png|haskell::pure]]<br />
<br />
--[[User:Rgreayer|Rgreayer]] 20:44, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
Find a font where 'k' looks like a reverse lambda (after removing the "stalk"). For example:<br />
<br />
[[Image:Kaskell.png|Kaskell]]<br />
<br />
Note this example uses Monotype Corsiva which is not a free font. If the basic approach looks good, we can find a similar free font that<br />
works.<br />
<br />
--[[User:Orenbenkiki|OrenBenKiki]] 01:40, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[http://relapse-software.net/haskell_5.png http://relapse-software.net/haskell_5.png]<br />
<br />
----<br />
<br />
[[Image:Haskell.png|Haskellll]]<br />
<br />
Illustrator, vector art available, apologies to GokhanSan<br />
<br />
--[[User:Mpeter|Mpeter]] 10:18, 15 December 2008 (UTC)<br />
<br />
----<br />
<br />
<br />
[http://relapse-software.net/haskell_6.png http://relapse-software.net/haskell_6.png]<br />
<br />
----<br />
<br />
[[Image:Haskell3.png|Haskell]]<br />
[[Image:Haskell4.png|Haskell]]<br />
<br />
Inkscape, vector art available.<br />
<br />
--[[User:Chromakode|Chromakode]] 07:14, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
I'll probably regret this...<br />
<br />
[[Image:NarleyYeeaaahh.jpg|Haskell - Narwals, YEEAAAAHH!!]]<br />
<br />
(Created with PAINT.NET)<br />
<br />
--[[User:Reified|Reified]] 07:20, 16 December 2008 (UTC)<br />
:It's a fun one but I erroneously read " Chaskell YEEAAAHH!! " [[User:Ripounet|Ripounet]]<br />
----<br />
<br />
The general idea is that it's just "Haskell" but with w lambda instead of the a. The font here is Myriad Pro but this would work with any<br />
good sans-serif font. It's color-agnostic, so it can be easily printer, presented as white on black or changed to a different color.<br />
<br />
[[Image:Haskell_logo_bonus.png]]<br />
<br />
[[Image:Haskell_logo_bonus2.png]]<br />
<br />
--[[User:BONUS|BONUS]] 14:40, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Axman6-logo-1.0.png]]<br />
<br />
In black:<br />
<br />
[[Image:Axman6-logo-1.1.png]]<br />
<br />
[[Image:Axman6-logo-1.1-small.png]]<br />
<br />
--[[User:Axman6|Axman6]] 15:16, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Haskell_girl.jpg]]<br />
<br />
<br />
Oh, didn't know png's would work.<br />
--[[User:Tindrum|Tindrum]] 17:12, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Haskell_logo.png]]<br />
<br />
It is mutually recursive...<br />
Here is the [[Media:Haskell logo.svg|svg]].<br />
<br />
Second version:<br />
<br />
[[image:Haskell2_logo.png]]<br />
<br />
And the [[Media:Haskell2 logo.svg|svg]].<br />
<br />
--[[User:Trontonic|Trontonic]] 20:39, 16 December 2008 (UTC)<br />
<br />
----<br />
This is a variation on my [http://t-shirts.cafepress.com/item/lambda-revolution-fitted-tshirt/96543210 Cafepress t-shirt]. The PNG is<br />
generated from an Inkscape SVG.<br />
<br />
[[Image:Haskell-logo-revolution.png]]<br />
<br />
Adjectives: revolutionary<br />
<br />
[[User:PaulJohnson|PaulJohnson]] 21:08, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:haskell-cjay.png]]<br />
<br />
Available as [[Media:Haskell-cjay.svg|svg]] (inkscape). Fonts: FreeSerif for lambda and >>. Bitstream Vera and FreeMono for other (afaik<br />
all free to use)<br />
<br />
[[User:Cjay|cjay]] 22:45, 16 December 2008 (UTC)<br />
<br />
----<br />
<br />
http://conal.net/Pan/Gallery/haskell-powered%20on%20white%20tiled%20360.png<br />
<br />
One I made with [http://conal.net/Pan/Gallery Pan] (purely functional image synthesis in Haskell) some years back. See also the<br />
[http://conal.net/Pan/Gallery/haskell-powered%20on%20white%20tiled%20720.png 720 square version]. I have a few sizes up to 2250 pixels<br />
square.<br />
<br />
[[User:Conal|Conal]] 03:40, 17 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[image:Haskell_lambda.png]]<br />
<br />
Just kidding :P<br />
<br />
--[[User:Trontonic|Trontonic]] 05:04, 17 December 2008 (UTC)<br />
<br />
----<br />
=== Cale Gibbard ===<br />
[[Image:Haskell-logo-6up.png]]<br />
<br />
[http://haskell.org/haskellwiki/Image:Haskell-logo-6up.svg Inkscape SVG]<br />
<br />
I originally had no specific mountain in mind, but Don Stewart pointed out that this might be representative of Mt. Hood in Portland, Oregon, where Haskell was named.<br />
<br />
Regardless, I thought a summit, bathed in the pure mountain air would be a decent symbol for Haskell, the peak of contemporary programming. :)<br />
<br />
[[User:CaleGibbard|CaleGibbard]] 05:55, 17 December 2008 (UTC)<br />
:Here's a modified version with a slightly funkier font :) I think that it matches the lines of the image better... [[User:Porges|Porges]] 03:14, 18 December 2008 (UTC)<br />
<br />
[[Image:Testhask.png]]<br />
----<br />
<br />
Probably not a good choice for a logo:<br />
<br />
[[Image:Hazard lambda cracked 2.png]]<br />
<br />
----<br />
<br />
[[Image:Haskell_Ribbons.png]]<br />
<br />
[http://slipgate.za.net/~korpse/misc/Haskell_Ribbons.svg SVG]<br />
<br />
Simplicity.<br />
<br />
(It is possible that the font may need to be replaced with a free alternative.)<br />
<br />
[[User:Jonathanj|JonathanJ]] 16:34, 17 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Haskelllogosmax.png]]<br />
<br />
Available as SVG.<br />
<br />
[[User:MaxRabkin|MaxRabkin]] 05:37, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:DoHaskell.png]]<br />
<br />
Another variation for the cognicenti:<br />
<br />
[[Image:JustHaskell.png]]<br />
<br />
--[[User:Warren|Warren]] 07:26, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
A slight variation of the ">\=" logo:<br />
<br />
[[Image:haskell-logo-doublef.png]]<br />
<br />
Not that it's worth much:). Available as [[Media:haskell-logo-doublef.svg|SVG]].<br />
<br />
[[User:Doublef|DoubleF]] 07:36, 18 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:haskell-apankrat.png]]<br />
<br />
The idea for this [http://en.wikipedia.org/wiki/Wordmark_(graphic_identity) wordmark] is to modify ''A'' to resemble λ and through this tie together the "Haskell" to the "Lambda". Modified ''A'' also works well as a standalone logo:<br />
<br />
[[Image:haskell-symbol-apankrat.png]]<br />
<br />
Note that ''any'' logo based on the unmodified λ symbol may look ambiguous to the people outside of Haskell community. While the λ in the context of programming languages is clearly associated with functional programming, it ''is'' a lowercase Greek L and so it's reasonable for an outsider to associate it with '''L'''isp, and not Haskell.<br />
<br />
PS. I just scrolled up and saw BONUS'es entry (14:40, 16 December 2008). While its idea is close, I think using pure λ in place of an A doesn't work because it effectively turn the name into H-L-skell.<br />
<br />
[[User:Apankrat|Apankrat]] 07:38, 18 December 2008 (UTC)<br />
<br />
<br />
----<br />
A very simple logo, made with inkscape, using math fonts, with various grades (B&W, grays, fill color & gradient) and backgrounds<br />
[[Image:Simple_haskell.png]]<br />
<br />
SVG available here:<br />
[[Image:Simple haskell.svgz]]<br />
<br />
[[User:Aubanel|Aubanel]] 18:08, 18 December 2008 (UTC)<br />
<br />
<br />
<br />
----<br />
<br />
[[Image:g3634.png]]<br />
<br />
Available as Inkscape [[Media:dessin.svg|SVG]]<br />
<br />
[[Image:g4441.png]]<br />
<br />
Available as Inkscape [[Media:dessin2.svg|SVG]]<br />
<br />
[[User:runrun|runrun]] 18 December 2008<br />
<br />
----<br />
<br />
[[Image:Haskell-logo2-max.png]]<br />
<br />
Contact me for SVG. Font is not currently free, but I designed it, so this can change if it becomes "the Haskell font". I think it shows some of the elegance that Haskell has. If you like the font but can put it with a better logo, go ahead. --[[User:MaxRabkin|MaxRabkin]] 04:53, 19 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:sgf.png]]<br />
<br />
I think the best way to represent the pure, functional nature of Haskell is with a pure and functional logo! Something modernist, minimalist, clean and simple. I'd prefer not to put highlights of the language's syntax in the logo - that's remarkably concrete for a language good at abstraction. Even lambdas etc. should be slightly hidden - those who know what it's about can see them, and everyone else doesn't think 'what's that funny symbol?'. For the font, again, something functional like a light Helvetica or Univers.<br />
<br />
So, I thought I'd have a go at a few variations. I'm not convinced it's worked, but there you go. I've shamelessly ripped off tanimoto's idea. [[User:Sgf|Sgf]] 08:13, 19 December 2008 (UTC)<br />
<br />
* Sgf, I really like your logos and I think you captured my idea much better than I could do. I especially like the red one, a bit Escher-esque. I wonder if we could turn the blue one into something that looks more like a snowflake than it currently does. Thanks. [[User:Tanimoto|tanimoto]] 10:43, 19 December 2008 (UTC)<br />
<br />
* I also like the blue and the red logo. The resemblance of a snowflake fits the purity of the language. Perhaps you could give the lambda's more volume to make it more plate-like? [[User:Felix|Felix]]<br />
<br />
* Thanks for the comments. I'm going to be offline for about a week, so I'm not going to have a chance to knock up further variations soon, much as I would like to. So, if you have the time, feel free to generate variations from the [[Media:sgf.svg|Inkscape SVG]]. Otherwise, I'll have a go when I get back. Cheers, [[User:Sgf|Sgf]] 01:48, 20 December 2008 (UTC)<br />
<br />
[[Image:Sgf-logo-blue.png|Sgf-logo-blue]]<br />
<br />
Sgf's red logo changed to blue and with the Fonce Sans font that FalconNL has used for another logo. [[User:Felix|Felix]] 2008-12-21<br />
<br />
And another variation of Sgf's logo, this time using negative instead of positive space.<br />
<br />
[[Image:Haskell_logo_ideas_5_falconnl.png]]<br />
<br />
--[[User:FalconNL|FalconNL]] 18:13, 21 December 2008 (UTC)<br />
<br />
----<br />
<br />
Yet another variation on tanimoto and sgf's themes, with influences from others. The intent here is fun, pure, simple, complete, intriguing, and a bit paradoxical. (The loose relation to the Cabal logo was unexpected.) Font is Free Sans, but I'd look for better if I had a bit more time.<br />
<br />
[[Image:Hs_logos_sereven.png]]<br />
<br />
The compiler sits at the core in negative space, its form suggested by what is built on and around it. Also in negative space, lambdas and reflected lambdas link the golden base library to others, pure primary colours available ready to be combined. Libraries become dimensional as they fit together like puzzle pieces. At each layer they form a whole, complete, yet extensible in all directions.<br />
<br />
[[User:sereven|sereven]] 12:24, 22 December 2008 (UTC)<br />
<br />
----<br />
λλλ<br />
<br />
Haskell The Revenge of the Nerds<br />
<br />
---<br />
<br />
[[Image:Ouroborous-oval.png|Ouroboros oval]]<br />
<br />
Paulo Tanimoto on the mailing list suggested something based on [http://www.example.com Orouboros]. Here is the [[Media:Ouroborous-oval.svg|Inkscape SVG]].<br />
<br />
Adjectives: abstract, friendly<br />
<br />
[[User:PaulJohnson|PaulJohnson]]<br />
<br />
----<br />
<br />
How about using one of the mythical birds in lambda calculus? Specifically, the ones from the article [http://users.bigpond.net.au/d.keenan/Lambda/ To Dissect a Mockingbird]. Some of the examples:<br />
<br />
http://users.bigpond.net.au/d.keenan/Lambda/Graphical_lambda2.gif (Mockingbird)<br />
<br />
http://users.bigpond.net.au/d.keenan/Lambda/Graphical_lambda6.gif (Omega bird)<br />
<br />
http://users.bigpond.net.au/d.keenan/Lambda/Graphical_lambda15.gif<br />
<br />
Since Haskell is centered around the idea of lambdas, I thought this would be a cool idea. Plus, they have qualities similar to Haskell: exotic, mysterious, abstract... [[User:Aviator|Aviator]] 12:35, 21 December 2008 (UTC)<br />
<br />
----<br />
<br />
[[Image:Origami-lamdba-supernova-warp.png|The Haskell Origami Lambda's Warp from the Supernova]]<br />
This is an H composed of two identical vertically tiled lambdas warping from a supernova. It symbolizes the warp of the Haskell-lambda away from the O of object-orientation (symbolized by the supernova).<br />
<br />
Created in Inkscape, then adjusted in GIMP. This was my first try at using both tools. I have never done graphic design before.<br />
<br />
If I have time, I may submit a revised version.<br />
<br />
by [[User:DekuDekuplex|Benjamin L. Russell]] 22:17, 22 December 2008 (Tokyo Time)<br />
<br />
----<br />
<br />
[[Image:ClassyHLogo.png]]<br />
<br />
I created the current, apparently-much-loathed purple-and-green Haskell logo back in<br />
2004 at John Peterson's request. I actually sent him several designs, and I must admit <br />
I rather liked this one better, myself. I later included it on some of the<br />
CafePress merchandise as the "classy Haskell logo". It's main virtues are that it's <br />
sparse and abstract; it's specifically inspired by those hood ornaments you see on <br />
fancy cars (no relation to Andy Gill's Hood debugger).<br />
<br />
The fancy typeface goes a little against the grain of "sparse and abstract", but it's<br />
of course independent from the logo itself.<br />
<br />
The simplicity of the logo proper (modulo the shadow and the typeface) makes it easy to <br />
reproduce in SVG and the like.<br />
<br />
(For a brief time, this logo was available on CafePress in the form of a frisbee, er, <br />
"flying disc", but they stopped carrying the item. It has been available for a while <br />
on shirts and perhaps mugs as well.)<br />
<br />
Anyway, perhaps it will appeal to others over the current one as much as it did to me.<br />
<br />
by [[User:FritzRuehr|Fritz Ruehr]]</div>Jsnxhttps://wiki.haskell.org/index.php?title=Generalised_algebraic_datatype&diff=24505Generalised algebraic datatype2008-12-05T17:32:20Z<p>Jsnx: This link is broken. Tried to find the talk but so far, no luck.</p>
<hr />
<div>== Papers ==<br />
<br />
See also [[Research papers/Type systems#Generalised Algebraic Data Types|research papers on type systems]].<br />
<br />
* A short description on generalised algebraic datatypes here [http://www.haskell.org/ghc/docs/latest/html/users_guide/data-type-extensions.html#gadt as GHC language features].<br />
* Another description with links on [http://hackage.haskell.org/trac/haskell-prime/wiki/GADTs Haskell' wiki].<br />
* [http://techreports.library.cornell.edu:8081/Dienst/UI/1.0/Display/cul.cis/TR2003-1901 First-Class Phantom Types] by James Cheney and Ralf Hinze<br />
* [http://cristal.inria.fr/~fpottier/publis/pottier-regis-gianas-05.pdf Stratified type inference for generalized algebraic data types] by François Pottier and Yann Régis-Gianas. It contains also a lot of links to other papers on GADTs.<br />
* [http://research.microsoft.com/Users/simonpj/papers/gadt/index.htm Simple unification-based type inference for GADTs] by Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Geoffrey Washburn. (Revised April 2006.)<br />
* [http://www.comp.nus.edu.sg/~sulzmann/manuscript/simple-translate-gadts.ps Translating Generalized Algebraic Data Types to System F] written by [http://www.comp.nus.edu.sg/~sulzmann/ Martin Sulzmann] and Meng Wang. [http://www.comp.nus.edu.sg/~sulzmann/2005.html Many other papers]. The talk mentions also the notion of [[phantom type]], and [[existential type]], and [[type witness]].<br />
<br />
== Motivating example ==<br />
<br />
Generalised Algebraic Datatypes (GADTs) are datatypes for which a constructor has a non standard type. Indeed, in type systems incorporating GADTs, there are very few restrictions on the type that the data constructors can take. To show you how this could be useful, we will implement an evaluator for the typed SK calculus. Note that the K combinator is operationally similar to<br />
<math>\lambda\;x\;y\;.\;x</math><br />
and, similarly, S is similar to the combinator<br />
<math>\lambda\;x\;y\;z\;.\;x\;z\;(\;y\;z\;)</math><br />
which, in simply typed lambda calculus, have types<br />
<math>a \rightarrow b \rightarrow a </math><br />
and<br />
<math>(a \rightarrow b \rightarrow c) \rightarrow (a \rightarrow b) \rightarrow a \rightarrow c </math><br />
Without GADTs we would have to write something like this:<br />
<haskell><br />
data Term = K | S | Term :@ Term <br />
infixl 6 :@<br />
</haskell><br />
With GADTs, however, we can have the terms carry around more type information and create more interesting terms, like so:<br />
<haskell><br />
data Term x where<br />
K :: Term (a -> b -> a)<br />
S :: Term ((a -> b -> c) -> (a -> b) -> a -> c)<br />
Const :: a -> Term a<br />
(:@) :: Term (a -> b) -> (Term a) -> Term b<br />
infixl 6 :@<br />
</haskell><br />
now we can write a small step evaluator:<br />
<haskell><br />
eval::Term a -> Term a<br />
eval (K :@ x :@ y) = x<br />
eval (S :@ x :@ y :@ z) = x :@ z :@ (y :@ z)<br />
eval x = x<br />
</haskell><br />
Since the types of the so-called object language, being the typed SK calculus, are mimicked by the type system in our meta language, being Haskell, we have a pretty convincing argument that the evaluator won't mangle our types. We say that typing is preserved under evaluation (preservation.) Note that this is an argument and not a proof.<br />
<br />
This, however, comes at a price: let's see what happens when you try to convert strings into our object language:<br />
<haskell><br />
parse "K" = K<br />
parse "S" = S<br />
</haskell><br />
you'll get a nasty error like so:<br />
<br />
Occurs check: cannot construct the infinite type: c = b -> c<br />
Expected type: Term ((a -> b -> c) -> (a -> b) -> a -> b -> c)<br />
Inferred type: Term ((a -> b -> c) -> (a -> b) -> a -> c)<br />
In the definition of `foo': foo "S" = S<br />
<br />
One could, however, reason that parse has type: <hask>String -> exists a. Term a</hask>, see also [[Existential type]].<br />
<br />
== Example with lists ==<br />
<br />
here's another, smaller example:<br />
<haskell><br />
data Empty<br />
data NonEmpty<br />
data List x y where<br />
Nil :: List a Empty<br />
Cons:: a -> List a b -> List a NonEmpty<br />
<br />
safeHead:: List x NonEmpty -> x<br />
safeHead (Cons a b) = a<br />
</haskell><br />
<br />
now safeHead can only be applied to non empty lists, and will never evaluate to bottom. This too comes at a cost; consider the function:<br />
<br />
<haskell><br />
silly 0 = Nil<br />
silly 1 = Cons 1 Nil<br />
</haskell><br />
<br />
yields an objection from ghc:<br />
Couldn't match `Empty' against `NonEmpty'<br />
Expected type: List a Empty<br />
Inferred type: List a NonEmpty<br />
In the application `Cons 1 Nil'<br />
In the definition of `silly': silly 1 = Cons 1 Nil<br />
<br />
== Parsing Example ==<br />
<br />
Note that GADTs provide a rather nice platform for embedded domain specific languages. In particular, they allow an [[EDSL]] to use Haskell's type system for its own purposes. As a simple example, we might have an EDSL for simple (regexp-like) parsers that looks something like:<br />
<br />
<haskell><br />
data Parser tok a where<br />
Zero :: Parser tok ()<br />
One :: Parser tok ()<br />
Check :: (tok -> Bool) -> Parser tok tok<br />
Satisfy :: ([tok] -> Bool) -> Parser tok [tok]<br />
Push :: tok -> Parser tok a -> Parser tok a<br />
Plus :: Parser tok a -> Parser tok b -> Parser tok (Either a b)<br />
Times :: Parser tok a -> Parser tok b -> Parser tok (a,b)<br />
Star :: Parser tok a -> Parser tok [a]<br />
</haskell><br />
<br />
An evaluator/parser is then straightforward. Below it's written monadically for<br />
convenience, but this also means that we could generalise the return type to being in any MonadPlus. Note that an advantage of this representation which we don't show here is that we could also write a function which applies algebraic rules to the structure to try to simplify the parser before running it. (Though if we were really concerned with efficiency, we'd probably also need a couple more primitives.)<br />
<br />
<haskell><br />
parse :: Parser tok a -> [tok] -> Maybe a<br />
<br />
-- Zero always fails.<br />
parse Zero ts = mzero<br />
<br />
-- One matches only the empty string.<br />
parse One [] = return ()<br />
parse One _ = mzero<br />
<br />
-- Check p matches a string with exactly one token t such that p t holds.<br />
parse (Check p) [t] = if p t then return t else mzero<br />
parse (Check p) _ = mzero<br />
<br />
-- Satisfy p any string such that p ts holds.<br />
parse (Satisfy p) xs = if p xs then return xs else mzero<br />
<br />
-- Push t x matches a string ts when x matches (t:ts).<br />
parse (Push t x) ts = parse x (t:ts)<br />
<br />
-- Plus x y matches when either x or y does.<br />
parse (Plus x y) ts = liftM Left (parse x ts) `mplus` liftM Right (parse y ts)<br />
<br />
-- Times x y matches the concatenation of x and y.<br />
parse (Times x y) [] = liftM2 (,) (parse x []) (parse y [])<br />
parse (Times x y) (t:ts) = <br />
parse (Times (Push t x) y) ts `mplus`<br />
liftM2 (,) (parse x []) (parse y (t:ts))<br />
<br />
-- Star x matches zero or more copies of x.<br />
parse (Star x) [] = return []<br />
parse (Star x) (t:ts) = do<br />
(v,vs) <- parse (Times x (Star x)) (t:ts)<br />
return (v:vs)<br />
</haskell><br />
<br />
Finally, we might define some examples:<br />
<br />
<haskell><br />
token x = Check (== x)<br />
string xs = Satisfy (== xs)<br />
<br />
p = Times (token 'a') (token 'b')<br />
p1 = Times (Star (token 'a')) (Star (token 'b'))<br />
p2 = Star p1<br />
<br />
blocks :: (Eq tok) => Parser tok [[tok]]<br />
blocks = Star (Satisfy allEqual)<br />
where allEqual xs = and (zipWith (==) xs (drop 1 xs))<br />
<br />
evenOdd = Plus (Star (Times (Check even) (Check odd)))<br />
(Star (Times (Check odd) (Check even)))<br />
<br />
</haskell><br />
<br />
Testing this in ghci:<br />
<pre><br />
*Main> parse p "ab"<br />
Just ('a','b')<br />
*Main> parse p "ac"<br />
Nothing<br />
*Main> parse p1 "aaabbbb"<br />
Just ("aaa","bbbb")<br />
*Main> parse p2 "aaabbbbaabbbbbbbaaabbabab"<br />
Just [("aaa","bbbb"),("aa","bbbbbbb"),("aaa","bb"),("a","b"),("a","b")]<br />
*Main> :t p2<br />
p2 :: Parser Char [([Char], [Char])]<br />
*Main> parse blocks "aaaabbbbbbbbcccccddd"<br />
Just ["aaaa","bbbbbbbb","ccccc","ddd"]<br />
*Main> parse evenOdd [0..9]<br />
Just (Left [(0,1),(2,3),(4,5),(6,7),(8,9)])<br />
*Main> parse evenOdd [1..10]<br />
Just (Right [(1,2),(3,4),(5,6),(7,8),(9,10)])<br />
<br />
</pre><br />
<br />
== Projects containing GADTs ==<br />
<br />
Papers on [[Libraries and tools/Database interfaces/HaskellDB|HaskellDB]] describe problems when GADTs can help (but HaskellDB solves these problems with [[phantom type]]s).<br />
<br />
[[Darcs]] represents motivating examples for GADTs, too -- and uses them.<br />
The motivations are described in David Roundy's FOSDEM slides (Implementing the Darcs Patch Formalism and Verifying It) (see p. 11, 13--14.). The talk mentions also the notions of [[phantom type]], and [[existential type]], and [[type witness]] (see p. 15).<br />
<br />
== See also ==<br />
<br />
[[Algebraic data type]]<br />
<br />
<br />
[[Category:Glossary]]<br />
[[Category:Language extensions]]</div>Jsnx