

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rodrigo Kumpera Weblog &#187; haskell</title>
	<atom:link href="http://www.kumpera.net/blog/index.php/tag/haskell/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kumpera.net/blog</link>
	<description>Meus achados sobre tecnologia</description>
	<lastBuildDate>Mon, 30 Aug 2010 12:00:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Implementando Haskell em VMs tradicionais (parte 2)</title>
		<link>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/</link>
		<comments>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 23:30:36 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=149</guid>
		<description><![CDATA[Retomando a questão sobre como implementar Haskell em VMs tradicionais, vamos ver um dos aspectos mais complicados, thunking, de implementar de forma eficiente. Um dos aspectos que surpreende a maioria dos que usam Haskell pela primeira vez é o fato da linguagem ser lazy evaluated, isto é, o valor de uma expressão só é computado [...]]]></description>
			<content:encoded><![CDATA[<p>Retomando a questão sobre <a href="http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/">como implementar Haskell em VMs tradicionais</a>, vamos ver um dos aspectos mais complicados, thunking, de implementar de forma eficiente. Um dos aspectos que surpreende a maioria dos que usam Haskell pela primeira vez é o fato da linguagem ser lazy evaluated, isto é, o valor de uma expressão só é computado quando for usado, mesmo entre chamadas funções. Vejamos um exemplo simples:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">square a <span style="color: #339933; font-weight: bold;">=</span> a <span style="color: #339933; font-weight: bold;">*</span> a
&nbsp;
square<span style="color: #339933; font-weight: bold;">_</span>of<span style="color: #339933; font-weight: bold;">_</span>sum a b <span style="color: #339933; font-weight: bold;">=</span> square <span style="color: green;">&#40;</span>a <span style="color: #339933; font-weight: bold;">+</span> b<span style="color: green;">&#41;</span></pre></div></div>

<p>Nesse exemplo, quando square_of_sum chama square, o parâmetro passado não é o resultado de a + b, mas sim algo próximo a uma closure que irá calcular a + b. Quando square for avaliada, ela precisará do valor de &#8216;a&#8217;, então usará a closure que recebeu como parâmetro para tal. Ou melhor, funciona quase assim, Haskell implementa um mecanismo chamado call-by-need, que resolve o valor uma única vez na primeira vez que for necessário memorizando o resultado. Isso significa que no caso de square &#8216;a&#8217; será avaliada uma única vez. Por conta da memorização, não usamos o termo closure, mais sim thunk para descrever o que uma função passa para outra.</p>
<p>Outro detalhe importante, chamadas de função também são lazy evaluated, então tanto square, quanto square_of_sum na verdade retornam thunks para os valores em questão. Essa coisa toda pode parecer extremamente ineficiente a primeira vista e de fato é. Tanto que o GHC gera código sem uso de thunk sempre que conseguir provar que um pedaço de código pode ser strict evaluated [1].</p>
<p>Antes de imaginar como implementar isso em uma VM como a CLR, vamos traduzir nosso exemplo para C# [2]:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">&nbsp;
<span style="color: #FF0000;">class</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	T value<span style="color: #008000;">;</span>
	Func<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> closure<span style="color: #008000;">;</span>
	<span style="color: #FF0000;">bool</span> resolved<span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> Thunk <span style="color: #000000;">&#40;</span>Func<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> closure<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">closure</span> <span style="color: #008000;">=</span> closure<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> T Value <span style="color: #000000;">&#123;</span>
		get <span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>resolved<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
				value <span style="color: #008000;">=</span> closure <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				resolved <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
				closure <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">return</span> value<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">*</span> a.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square_of_sum <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a, Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a_plus_b <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">+</span> b.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">return</span> square <span style="color: #000000;">&#40;</span>a_plus_b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Já que square produz um thunk, não precisamos criar outro.</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Bem confuso, de certo. Primeiro a implementação de Thunk, simples e direta, já square_of_sum precisa de uma variável local para ficar minimamente legível. Uma coisa é fato, C# não foi feita para ser usada com lazy evaluation.</p>
<p>Existe alguns problema quanto a eficiencia de fazer dessa forma. O maior deles é como lidar quando alguns valores já estão resolvidos e temos ainda assim criar um thunk para satisfazer o função chamada. A forma como GHC lida isso é passando todos parâmetros boxed de forma que é possível misturar thunks e valores sem problema. A função square, do nosso exemplo anterior ficaria assim:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #FF0000;">int</span> val<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>a <span style="color: #008000;">is</span> <span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>
			val <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>a<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">else</span>
			val <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span>Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#41;</span>a<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
		<span style="color: #0600FF;">return</span> val <span style="color: #008000;">*</span> val<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Outra forma de também lidar com esse problema é criar duas versões da mesma função, uma que recebe valores resolvidos e outra apenas thunks. Fazer dessa forma é vantagem quando podemos provar o uso estrito dos valores em questão. Por fim, acho que o maior problema ser achar uma forma de representar um thunk usando o mínimo possível de memória.</p>
<p>No nosso exemplo, em uma plataforma 32bits, Trunk<T> usa 20 bytes, Func<T> usa mais 40 e outros 8 da closure[3]. Ou seja, começa usando 68, coisa pacas. Podemos fazer algumas mudanças nisso. Dado que não existe null em Haskell podemos remover o atributo resolved e simplesmente verificar se closure é ou não null. Segundo, em vez criar 1 delegate toda vez podemos fazer caching dele e armazenar as variáveis capturadas no próprio thunk. Algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">abstract <span style="color: #FF0000;">class</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">public</span> abstract T Value <span style="color: #000000;">&#123;</span> get<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> ThunkWithVars<span style="color: #008000;">&lt;</span>T,V<span style="color: #008000;">&gt;</span> <span style="color: #008000;">:</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	T value<span style="color: #008000;">;</span>
	Func<span style="color: #008000;">&lt;</span>V, T<span style="color: #008000;">&gt;</span> closure<span style="color: #008000;">;</span>
	V vars<span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> ThunkWithVars <span style="color: #000000;">&#40;</span>Func<span style="color: #008000;">&lt;</span>V,T<span style="color: #008000;">&gt;</span> closure, V vars<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">closure</span> <span style="color: #008000;">=</span> closure<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">vars</span> <span style="color: #008000;">=</span> vars<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> T Value <span style="color: #000000;">&#123;</span>
		get <span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>closure <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
				value <span style="color: #008000;">=</span> closure <span style="color: #000000;">&#40;</span>vars<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				closure <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
				vars <span style="color: #008000;">=</span> <span style="color: #0600FF;">default</span> <span style="color: #000000;">&#40;</span>V<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">return</span> value<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">static</span> Func<span style="color: #008000;">&lt;</span>Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span>, <span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square_resolve <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>a<span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">*</span> a.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> ThunkWithVars<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span>, Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;&gt;</span> <span style="color: #000000;">&#40;</span>square_resolve, a<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Usando essa codificação Thunk continua usando 20 bytes porém nos livramos dos demais objetos, um ganho de 70% no final das contas. Poderíamos economizar outros 4 se juntarmos as variáveis closure e value em uma só caso T fosse do tipo referência &#8211; ou manter o resultado boxed. Mesmo sem isso, 20 bytes já é um valor razoável, conseguir o mesmo em uma JVM é basicamente impossível sem muita ginástica.</p>
<p>Qual a performance dessa solução? Segundo o pessoal do GHC, em média 95%-98% dos thunks gerados são resolvidos. Com um generational GC, a maioria vira lixo efêmero. Ou seja, não existe muita razão para uma VM tradicional ser mais lenta que a do GHC, o principal fator nesse caso é, sem dúvida, o compilador, que pode gerar pedaços de código inteiros sem uso de thunk.</p>
<p>[1] É muito comum em Haskell gerar código que não funciona sem lazy evaluation, como geradores de listas infinitas.<br />
[2] Nesse exemplo vou trapacear e tornar as funções mono-mórficas e usar int no lugar de Number para simplificar o código.<br />
[3] Nesse caso estou ignorando quanto de memória as variáveis capturadas usam.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementando Haskell em VMs tradicionais (parte 1)</title>
		<link>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 00:49:24 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[clr]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=138</guid>
		<description><![CDATA[Outro dia uma discussão me levou a pensar se era possível implementar Haskell em cima de uma VM tradicional, tal qual JVM ou CLR, de forma eficiente. Em termos dos mecanismos que a VM precisa suportar de forma eficiente os principais são tail call, thunking, type classes e algebraic types. Nesse artigo vou apenas discutir [...]]]></description>
			<content:encoded><![CDATA[<p>Outro dia uma discussão me levou a pensar se era possível implementar Haskell em cima de uma VM tradicional, tal qual JVM ou CLR, de forma eficiente. Em termos dos mecanismos que a VM precisa suportar de forma eficiente os principais são tail call, thunking, type classes e algebraic types. Nesse artigo vou apenas discutir um deles, type classes.</p>
<p>Uma type class para os acostumados com OO pode ser vista como uma interface cuja implementações são externas aos tipos que estão atrelados. Um exemplo bem simples é Eq, que permite compar objetos do mesmo tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">class</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> a <span style="color: #06c; font-weight: bold;">where</span>
    <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">==</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span> <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">/=</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">::</span> a <span style="color: #339933; font-weight: bold;">-&gt;</span> a <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: #cccc00; font-weight: bold;">Bool</span>
    x <span style="color: #339933; font-weight: bold;">/=</span> y <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>x <span style="color: #339933; font-weight: bold;">==</span> y<span style="color: green;">&#41;</span>
    x <span style="color: #339933; font-weight: bold;">==</span> y <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>x <span style="color: #339933; font-weight: bold;">/=</span> y<span style="color: green;">&#41;</span></pre></div></div>

<p>Para nos não iniciado em Haskell, linha um define a classe Eq e diz que ela possui um parâmetro polimófico; linha 2 diz que Eq tem 2 funções, &#8220;==&#8221; e &#8220;/=&#8221; cuja assinatura são dois valores do tipo &#8216;a&#8217; e retorna um booleano; por fim, linhas 3 e 4 são implementações padrão das funções. Seria o equivalente, em pseudo-C#, ao seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
   <span style="color: #FF0000;">bool</span> <span style="color: #0600FF;">operator</span><span style="color: #008000;">==</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #008000;">!</span><span style="color: #000000;">&#40;</span>a <span style="color: #008000;">!=</span> b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
   <span style="color: #FF0000;">bool</span> <span style="color: #0600FF;">operator</span><span style="color: #008000;">!=</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #008000;">!</span><span style="color: #000000;">&#40;</span>a <span style="color: #008000;">==</span> b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Uma das vantagens de type classes no Haskell é que elas podem fornecer implementações padrão para alguns de seus métodos. Bom, agora que temos Eq definida, para dizer que Listas a implementa usamos algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">instance</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> a <span style="color: #339933; font-weight: bold;">=&gt;</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> <span style="color: green;">&#91;</span>a<span style="color: green;">&#93;</span> <span style="color: #06c; font-weight: bold;">where</span>
    <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">=</span> True
    <span style="color: green;">&#40;</span>x:xs<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: green;">&#40;</span>y:ys<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> x<span style="color: #339933; font-weight: bold;">==</span>y <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> xs<span style="color: #339933; font-weight: bold;">==</span>ys
    <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">=</span> False</pre></div></div>

<p>Aqui vemos uma das melhores características do Haskell é explorada, que é pattern matching &#8211; e isso também é assunto para outro artigo. Como pode se notar, uma implementação de uma dada type class não está embutida na definição do tipo em questão, ou seja, não podemos interfaces como a CLR ou a JVM suportam.</p>
<p>A idéia é representar type classes de forma semelhante a como o ghc faz, usando dictionary passing[1], que é bem simples de entender e implementar. Para cada type class que uma função recebe nos seus parâmetros, passamos junto um objeto que representa as operações em questão. Em C# teríamos:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">bool</span> op_neq <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> Eq_Int <span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">==</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">!=</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">int</span> Fun<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span>Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> dict, T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>dict.<span style="color: #0000FF;">op_eq</span> <span style="color: #000000;">&#40;</span>a, b<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Existe alguns problemas aqui, primeiro que estamos passando um parâmetro extra e segundo que não é possível eliminar a verificar por null pointer caso op_eq seja inlined. A solução é razoavelmente simples no caso do C#:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">struct</span> Eq_Int <span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">==</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_neq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">!=</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">int</span> Fun<span style="color: #008000;">&lt;</span>T, TD<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> where TD<span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">default</span> <span style="color: #000000;">&#40;</span>TD<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">op_eq</span> <span style="color: #000000;">&#40;</span>a, b<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>A grande mudança aqui é tornar a instância da typeclass um valuetype e construir um valor default para satisfazer o compilador. É uma pena que não podemos simplesmente chamar um método estático e TD, o que é uma limitação boba da CLR. Essa solução não é possível na JVM devido a inexistência de valuetypes e generics.</p>
<p>E quanto a performance dessa solução? Bom, no caso do mono, o JIT&#8217;er reconhece as chamadas como não virtuais e é capaz de fazer inline de forma bem agressiva &#8211; exatamente como desejado. Eu pensei em fazer um comparativo dessa solução com o equivalente em Java, mostrando como a CLR permite codificar tipos muito mais ricos e interessantes que a JVM &#8211; e como isso se traduz em performance. Mas realmente não estou afim de criar motivo para um flamewar por parte dos javeiros de plantão.</p>
<p>[1]Esse é o paper original que descreve type classes e a técnica utilizada: http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Limites da orientação a objetos</title>
		<link>http://www.kumpera.net/blog/index.php/2009/08/30/limites-da-orientacao-a-objetos/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/08/30/limites-da-orientacao-a-objetos/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 20:00:06 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[plt]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[type systems]]></category>
		<category><![CDATA[typeclasses]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=136</guid>
		<description><![CDATA[Toda linguagem de programação pode ser analisada pela sua junção de três elementos distintos: forma, comportamento e taxonomia. Cada um define um aspectodistinto de como o conjunto de valores que compõe um programa é usado.
Cada um destes valores possui um forma, que é a representação concreta para o conceito abstrato que cada um significa. Um [...]]]></description>
			<content:encoded><![CDATA[<p>Toda linguagem de programação pode ser analisada pela sua junção de três elementos distintos: forma, comportamento e taxonomia. Cada um define um aspectodistinto de como o conjunto de valores que compõe um programa é usado.</p>
<p>Cada um destes valores possui um forma, que é a representação concreta para o conceito abstrato que cada um significa. Um array de bytes e uma lista de chars são duas maneiras de representar uma string &#8211; um conceito abstrato. Forma admite composição e extensão, mas isso é razoavelmente óbvio.</p>
<p>Por comportamento me refiro a um grupo que operações definido que operam em um dado conjunto de valores. Repetindo nosso exemplo, strings, podemos definir particionamento, remover espaços em branco e pois ai vai. Ou seja, nada mais simples que um conjunto de funções.</p>
<p>Por fim, taxonomia é como damos nomes a conjuntos de valores. Ruby, que usa um sistema nominal de tipos, damos um nome explicitamente a um dado conjunto de valores que irão habitar uma classe. Outro aspecto importante é que podemos usar os operadores da teoria de conjuntos para definir relações entre pares. Voltando a Ruby, a única relação é a de subconjunto, que é a herança entre duas classes.</p>
<p>São três elementos bem distintos, porém, linguagens OO misturam dois, as vezes mesmo todos. Por exemplo, classes são os três ao mesmo tempo, atributos a forma, métodos o comportamento e a taxonomia vem através da relação herança entre duas classes. Interfaces misturam comportamento e taxonomia. Mixins misturam forma e comportamento. O problema disso é quando você quer manipular apenas um e os outros vem de brinde.</p>
<p>Linguagens funcionais costumam lidar de forma mais efetiva com esse problema. Haskell separa muito bem isso, com datatypes para forma, funções lidam com o comportamento e typeclasses resolvem a questão da taxonomia. Dessa forma é possível focar apenas em um dos três sem nenhuma bagagem extra.</p>
<p>Um problema com haskell é que uma typeclass classifica todos habitantes de um dado tipo, não é possível fazer isso com uma parte apenas. Nesse sentido Qi possui um sistema de tipos muito interessante, baseado em sequent calculus, permitindo definir de forma mais precisa quais valores compõe um dado tipo.</p>
<p>Eu acredito que essa limitação da orientação a objetos é a razão pelo qual tantas pessoas preferem fugir para linguagens OO dinâmicas, que aliviam boa parte do problema dado que forma e taxonomia poder ser consideradas ad-hoc, agrada a vários, mas realmente não me agrada para construir sistema de grande escala.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/08/30/limites-da-orientacao-a-objetos/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
