Archive for February, 2007

Kit básico do escritor

Sunday, February 25th, 2007

Se você está lendo isto, provavelmente já tem a ferramenta mais fantástica que um escritor pode desejar: um computador! Dito isso, os softwares de apoio ao escritor mais utilizados não aproveitam ao máximo a flexibilidade que a máquina em cima da sua mesa disponibiliza. Descrevemos aqui, por isso, uma suíte de programas que, acreditamos, servirão melhor como apoio às suas atividades literárias.

A slightly better function-DOT dsl

Saturday, February 24th, 2007

In some of the graphs in Bycicling for Collatz (the divisibility graph with lots of arrows and the collatz one with 1, 2 and 4 highlighted) we manipulated the Haskell-generated graph either in the DOT file source or directly in the Graphviz GUI. The structure itself was somewhat confusing, too; the Dot class never managed to justify itself. Here’s a slightly cleaner version of that code to play with:

bikes.hs

module Bikes where

data Arr a = a :-> a
instance Functor Arr where fmap f (x:->y) = f  x :-> f y
instance (Show a) => Show (Arr a) where show (x:->y) = show x ++ " -> " ++ show y
arr f = (\x-> x :-> f x)
rra f = (\x-> f x :-> x)
data YellowGraph a = YG {
        why :: (a->Bool),
        func :: (a -> a),
        space :: [a]}
instance (Show a) => Show  (YellowGraph a) where
        show xs =  finalDot $ (toColorList xs) ++ (toArrList xs) where
                runGraph xs = (map (arr (func xs)) (space xs))
                filterGraph xs = (filter (why xs) (space xs))
                toArrList xs  = unlineAppend ";"  (runGraph xs)
                toColorList  xs = unlineAppend " [color = \"yellow\", style=\"filled\", shape=\"diamond\"];" (filterGraph xs)
                finalDot x = "digraph untitled {" ++ x ++ "}"
                unlineAppend d  = unlines . map ((++d) . show)        
graph f xs = YG { why = const False, func = f, space = xs}

jane = YG { why = even, func = (flip div 3), space = [1..80]}

The why parameter passed to the data constructor when you’re using the full syntax as in the jane example is a predicate that decides whether or not color a node yellow. Simple, color-less graphs can be produced with the auxiliary function graph.

Bicycling for Collatz

Thursday, February 22nd, 2007
Q: How many people with ADD does it take to change a lightbulb? A: HEY! Let’s ride bikes!

module Bikes where

Graphviz is fun. Graphviz is fair. You may already have one. You may already be there:

data Arr a = a :-> a

Graphviz plots graphs from .DOT files consisting of remarkably simple syntax:

instance (Show a) => Show (Arr a) where show (x:->y) = show x ++ " -> " ++ show y class (Show a) => (Dot a) where dot :: [a] -> String dot = (++”}”) . (”digraph untitled {”++) . unlines . map ((++”;”) . show) instance (Show a) => Dot (Arr a)

One fun thing we can do with it is plotting graphs of integer-valued functions:

arr f = (\x-> x :-> f x) rra f = (\x-> f x :-> x)

Let’s see what a simple invertible function looks like:

t2 = dot $ map (arr (*2)) [0..40]

Clearly there’s one and only one way to connect any given two nodes — which is what invertibility means. But let’s look at something fun now; say, the co-totient function. There’s a closed-form equation for this, but why not go full ape declarative?

totient x = x - (length $ [n | n<-[1..x], coprimes n x]) where coprimes a b = (gcd a b) == 1 t3 = dot $ map (arr totient) [1..100]

(Click to see full-size picture)

The first hierarchy line contains the prime numbers; their co-totient is always 1. These numbers are connected to numbers whose co-totient they are; from that graph you can find the co-totient of any number by looking at which number it’s connected to. At first glance it looks pretty tree-like, but it suffices to chase the series of powers of two to see it isn’t.

The Gee-Whiz Monad (I)

Monday, February 19th, 2007

[] is really the gee-whiz monad. Haskell code that prints *all the five-number combinations of integers in [-5..5]:

mapM (\x->[x+i | i<-[-5..5]]) [1..5]

No, really, try it. This has to qualify as the “most surprisingly long output” line of code in all of computer programming.

“But I/O is all I do in my web app. Why should I use Haskell?”

Thursday, February 15th, 2007

Well, use Rails, then. It seems to me that’s how I’d do a web app right now — the meaty logic would be in Haskell, and who cares about the rest anyway? At least Rails scaffolds it away.

IO doesn’t matter: telling C programmers the key to the Haskell weltanschauung

Thursday, February 15th, 2007

Quoth { continues here. }
{ 2 words, estimated 0 secs reading time)}

Recomeços

Wednesday, February 14th, 2007

Três forças movem o mundo: o interesse individual (às vezes aumentado com o bem-estar de familiares e entes queridos), a escassez material e a assimetria informacional. É pela primeira que agimos — não é tão diferente do eros freudiano, na essência. Pela segunda, somos obrigados a agir pelo interesse de outras pessoas pelas quais não temos particular afeto ou interesse. Pela terceira, vemo-nos constantemente forçados a provar o que somos: todos têm interesse de se passar por algo “melhor” do ponto de vista do interlocutor. Esse é o mundo: gravatas, carros, diplomas. Acordamos de manhã movidos pelo eros, pelo craving de dopamina ou pela simples fome de algo que encha a pança, e saímos ao mundo para oferecer o que temos, o que sabemos, o que conseguimos fazer — e para isso, temos que convencê-los de que temos todas essas coisas intangíveis que se negociam no mundo lá fora todos os dias. É daí que surge o jogo de segunda ordem; onde o jogo de primeira ordem é o mero mercado — de pão, plástico e carinho — este é o das reputações, das probabilidades de fraude, dos sistemas de incentivos compatíveis. Para convencer uma pessoa de que você agirá no interesse dela, precisa primeiro descrever um sistema no qual os seus interesses estão alinhados; precisa também mostrar que é suficientemente “bom” para que fosse muito caro para uma pessoa não-boa mostrar-se assim. É esse o papel das reputações: uma reputação é um investimento pesado acumulado ao longo de uma vida, e coloca-se a reputação como colateral numa transação em que há severo risco moral. Assim sendo, o seu cliente acredita que o interesse de ambos está alinhado — ele porque quer ver algo bem-feito, e você porque não fazer bem-feito abalará essa reputação que tão caro custa construir. Esse é o mundo. Bem-vindo!

O mundo funciona assim porque assim determina a dinâmica da interação da natureza humana com o mundo pré-singularidade tecnológica. Mas que aspectos do desejo humano são esmagados por essa dinâmica? Primeiro, a preguiça, a negação, o desejo de inação e de morte; é preciso sair para obter algo, qualquer coisa, qualquer pequeno estímulo neuroquímico — é preciso sair de casa e fazer algo. Segundo, o desejo infinito de sempre mais coisas omite o fato de que, apesar do crescimento e dos ganhos de troca, o mundo tem um pequeno botim a dividir entre muita gente, gente demais. Mas creio que o terceiro é o mais grave: todas as criaturas enfrentam e esmagam seu desejo de morte e seu desejo de infinito; o que de mais grave é negado ao homem pelo tecido social que sua dinâmica implica é o seu desejo de contínua reinvenção. Eu estive debatendo comigo mesmo importar textos antigos do velho blog blog journal ue diário, e acabei percebendo que a motivação era essa necessidade de provar a si mesmo. Mas se eu cedo ao jogo das reputações mantendo-me convenientemente anônimo por medo de quanto do meu futuro depende deles — dos heterodoxos, e dos heterodoxos de mente fechada (até onde sei são todos) — não esmago o meu desejo de tábula rasa tentando provar aos leitores deste blog blog journal ue diário que sou qualquer coisa. Aliás, reinventei-me mais uma vez ontem à noite, e talvez reinvente-me de novo depois do carnaval. Este também é o mundo, e se todos o aceitarmos, talvez sejamos mais felizes.

Opiniões

Tuesday, February 13th, 2007

[Nota: Sim, eu estou desviando do formato de dois parágrafos. Processe-me! O texto tem conotações pessoais (e não me refiro ao rumo da tal amizade, que é mais forte que circunstâncias tolas como esta) virtualmente recursivas, e não vale a pena correr o risco de ambigüidade que acompanha o texto maximalmente conciso.]

Sendo humanos, e portanto assessora de imprensa responsável pela manutenção dos blog blog journal ue diários da campanha de John Edwards, um dos pré-candidatos democratas à presidência dos EUA, viu-se obrigada a renunciar em vista de uma campanha da direita no sentido de associar seus pontos de vista heterodoxos sobre sexo, aborto e religião ao pré-candidato Edwards.

  • Segundo, uma velha amiga minha — quem há tempos insisto, sem sucesso, para que faça um blog blog journal ue diário — reverteu sua decisão técnica de escolher um ator para o filme que está dirigindo depois de saber incidentalmente de certas posições políticas suas. Isto é algo que esbarra no existencial, na náusea: o candidato manifestou uma opinião um tanto reacionária sobre um mendigo que procurava ajuda para o filho doente — e quando eu endossei horas depois (note-se que eu não estava lá, nem conheço o ator) a tal opinião, um pouco no espírito de advogado do diabo, a tal amiga resolveu desentender-se comigo.

    A questão comum levantada por estes dois episódios é, evidentemente, que tipo de opinião pode ser legitimamente usada como filtro em relações sociais aparentemente não relacionadas. Ora, a campanha Edwards e Amanda Marcotte tinham visões convergentes sobre a estratégia política a ser adotada, bem como esta minha amiga e seu ator tinham visões muito compatíveis — e produtivas em conjunto — sobre as questões criativas do filme. Estes dois exemplos sugerem, de fato, uma regra de bolso: as relações sociais deveriam independer de opiniões não-relacionadas. Assim sendo, faz todo o sentido que John Edwards não convie Amanda para reger o serviço religioso do batismo de suas filhas, ou que minha amiga cineasta rejeite o ator como articulador de uma campanha política. Esta ficaria sendo, afinal, uma aplicação do método deontológico. Ótimo quando estamos em um âmbito micropoliticamente estável — nossos amigos de confiança e os amigos de confiança dos amigos de confiança.

  • Ugh! Such a proud display of sheer irrationality

    Tuesday, February 13th, 2007

    [youtube=http://www.youtube.com/watch?v=Tr1qee-bTZI]

    What is this … person… going on about? She decries teaching some mathematical reasoning (”cluster methods”) in elementary school and wants to emphasize rote algorithm drill-and-kill work instead? She blames 18-year-olds not being able to handle logical reasoning on them not having memorized traditional arithmetic algorithms? She equates “maths” with “rote arithmetic”? It annoys me that she plays to the parents’ fear and ignorance against progress in teaching kids to think.

    What method do you really think would help kids to later be able to prove theorems in real analysis, operate group theory or grok category theory, “cluster” reasoning or repetitive algorithm crankery?

    Argh!

    Diamantes

    Monday, February 12th, 2007

    A lei da oferta e da demanda é algo maravilhoso; a sabedoria do mercado provém do fato de que a curva de oferta em geral é determinada por fatos hard, onde a curva de demanda reflete a psicologia humana; assim, o mercado ajusta os quereres aos poderes de forma demonstravelmente otimal. Mas claro, estas características básicas das funções de demanda e oferta são generalizações úteis. Veja-se o caso dos diamantes. Primeiro, a oferta é determinada basicamente por um monopolista, a companhia De Beers, e é um dos segredos mais conhecidos do mundo que eles guardam vastos estoques da pedra. Até aí tudo bem; um monopolista otimizador limita sua oferta, mas a assimetria informacional age contra ele. No entanto, a De Beers consegue limitar a oferta de segunda mão de diamantes através de uma combinação de fatores psicológicos (em algumas culturas, diamantes são eternos mesmo, apesar deste rito ter sido plantado mais ou menos na época que o Papai Noel da Coca-Cola nos anos 1940) e um controle rígido das joalherias e distribuidores que só recompram a pedra a preços muito mais baixos que os determinados pelo mercado. Devido a estes fatores, o preço do diamante não reflete a oferta física destas pedras, mas um gargalo artificial muito mais embaixo. Evidentemente, o preço do diamante pode estourar a qualquer momento, e talvez não haja suficiente mercado paralelo na eBay porque é cada vez mais difícil distingüí-los de sucedâneos cada vez mais sofisticado — dizem que muitos joalheiros mais antigos não conseguem identificar a moissanita, e a zircônia tem um brilho muito mais bonito que o da maioria dos diamantes.

    Finally some hacking of my own: a counter datatype

    Sunday, February 11th, 2007

    While examining ways to refactor the PFP library, it struck me that its strategy of storing repeated values and dealing with displaying them as an aggregate later was somewhat generalizable. This is a first stab at a counter datatype with constant-time update and (probably) O(m) lookup — where m is the sum of counts. The alternate strategy, using a Map, has O(log(n)) lookup and update time — where n is the number of counters.

    What do we want to do here?

    module Counter (count, inc, dec, empty, fromCounter, toCounter) where

    We want to store a list of values together with counts, e.g.

    *Counter> example "Rock" 18 "Jazz" 27 "Classical" 13 " Etc." 35

    We should be able to retrieve any count

    *Counter> count "Rock" example 18

    We want cheap inc

    *Counter> inc "Rock" example "Rock" 19 "Jazz" 27 "Classical" 13 " Etc." 35

    inc should handle gracefully (and still cheaply) new values:

    *Counter> inc "Traditional" example "Traditional" 1 "Rock" 18 "Jazz" 27 "Classical" 13 " Etc." 35

    There should be a functioning dec that also handles invalid cases gracefully:

    *Counter> dec "Classical" example "Rock" 18 "Jazz" 27 "Classical" 12 " Etc." 35 *Counter> dec "Mbembe" example "Rock" 18 "Jazz" 27 "Classical" 13 " Etc." 35

    There should be a simply empty counter so new counters can be constructed via inc chains:

    *Counter> inc False $ inc True $ inc False $ inc True empty False 2 True 2

    Finally, there should be convenience functions to construct a counter from a list of (key, count) pairs

    *Counter> toCounter [("Bjork",15),("Gentle Giant",12)] “Bjork” 15 “Gentle Giant” 12

    and to destruct a counter into such a list

    *Counter> fromCounter example [("Rock",18),("Jazz",27),("Classical",13),(" Etc.",35)]

    Here’s how we implement it.

    A counter is merely a list of values.

    Making a monad: Martin Erwig’s Dist

    Sunday, February 11th, 2007

    Much of statistical modelling involves shuffling around operations on stochastic variables — i.e. on their probability distributions. This can be tricky stuff: it either involves loads of manual lifting with fully discrete distributions or clever analytic methods for continuous ones. This is complicated enough that most of basic and intermediate-level applied statistical analysis is done working with a normality assumption; the normal distribution has some simple linearity properties regarding affine functions of normal stochastic variables, and is thus used to avoid dicking around with convolutions and the jacobian method.

    Like with Pancito, this is something I once independently tried to do, but got lost trying to model dense spaces and measure theory. Martin Erwig did the actual work so far, even though there’s no work in continuous spaces at all. I’m working on cleaning his code up — that is, making it more like the other GHC libraries, since this was done for an academic paper. I’d like to eventually turn this into Control.Stochastic; it’s not a Data.* library, as it allows for transititions, functions whose outcome depends on stochastic variables. This together with sigfpe’s CA comonad could lead to a very compact library for simulating percolation systems! In general, stochastic programming has wide, deep applications that make this econometrician’s eyes shine with hope.

    So after this short status report (apparently I finally manage to become interested enough to work on a project for a significant ammount of time), let’s take a look ath the centerpiece of Erwig’s PFP library: the Dist monad.

    First of all, probability is a measure over an algebra of events. Erwig doesn’t mull over too much on algebras, sigma-algebras and measure theory — I admire his restraint. Instead, we have merely the concept of an event: something that might or not happen.

    type Event a = a -> Bool

    Guido is wrong! for loops, declarativeness and Charlie Mingus

    Saturday, February 10th, 2007

    <

    ol>

  • Guido is wrong:

    brain-computer.jpg

  • <li>"<em>Each jazz musician when he </em> <a href="http://dayvancowboy.org/2007/02/guido-is-wrong-for-loops-declarativeness-and-charlie-mingus/#more-202" class="more-link">(more...)</a>
    

    Yet more silly text

    Friday, February 9th, 2007

    Mikael Johansson (whom I admire enough to have mentioned in my “about” page as one of the people I’d like to be more like, but am not) took the silly text generator from that post from a few hours ago and automatically translated to nadsat version.

    filename="nadground.txt"

    zip has smarter semantics on different-length lists than I thought; the contrived version of “pari” I had written is — as pointed out by Michi — simply

    pairs xs = zip xs (tail xs)

    I added some extra filtering; commas tend to lead to spaces too often and my text had some unicode characters (like fancy quote marks) that were bothering ghci

    bigram= pairs . map toLower . filter (\x -> (isAlpha x || isSpace x) && isAscii x && (not (isPunctuation x)))

    My actual probability distribution is based on tetragrams, though:

    tetragram = pairs . bigram distro = uniform . tetragram

    This is the conditional distribution; it picks a bigram with a probability that’s conditional on the previous bigram

    condDistro goal (x,y) = distro goal ||| (((a,b),(c,d))->(a==x)&&(b==y))

    In order not to have it too deterministic, we select only the first element of the conditioned bigram:

    pickAfter goal (x,y) = fmap (snd . snd) $ pick $ condDistro goal (x,y)

    This is kind of a dirty hack; we iterate this by mapping over a text that starts with the character we want. Some variation of forM probably fixes this, but I wanted to get this out as soon as possible.

    Some probabilistic text generation

    Friday, February 9th, 2007

    In the spirit of keeping a hacking blog journal — and toning the “functional john dvorak” tone — we exhibit a silly probabilistic text generator I worked on this morning.

    module Main where import Probability import Data.Char import Control.Monad

    Probabilityis Martin Erwig’s Probabilistic Functional Programming. I’m cleaning it up, haddockizing it and might cabalize it sometime soon. The stock copy will work for now, as I haven’t made any API changes yet.

    This function takes some text and returns a list of pairs of consecutive chars. For example, pari "some text" == [('s','o'),('o','m'),('m','e'),('e',' '),(' ','t'),('t','e'),('e','x'),('x','t')]

    pari xs = zip (firsts xs') (thens xs') where xs' = (map toLower . filter (\x->isAlpha x|| isSpace x)) xs firsts = take ((length xs) - 1) xs' thens = tail xs'

    Finally, we produce a probability distribution over the letter frequencies in a given string:

    distro xs = uniform $ pari xs

    We omit here the large goal string we used. It’s an arbitrary assemblage of text pasted from blog blog journal s linked at reddit. This function picks a pseudo-syllable: a pair of letters used in that order in the original text

    one =do { (a,b) <-pick goal; return [a,b];}

    Finally, we iterate (tee hee) over that:

    many n = fmap concat $ sequence $ take n $ repeat one

    Here is some of the deep abstract poetry produced by our program:

    for Whom The Bell Tolls

    Friday, February 9th, 2007

    The debate about adding closures to Java has spawned a curious debate about the role of explicit loops, recursion and higher-order list combinators. I wonder why no one has stepped up in defense of GOTO yet.

    Misguided Java snob Elliot Harold harangues fist and teeth against progress in computer languages:

    I don’t know what it is some people have against for loops that they’re so eager to get rid of them. This isn’t the first or even the second time CS theorists have revolted against for loops (or equivalent).

    This isn’t even the most proeminent below-the-belt jab at new expressive techniques. Take blog blog journal spot.com/2007/02/whats-wrong-with-for-loop.html”>oh, but wait, the traditional Bird-Merteens/Standard Prelude functions are kinda expressive too, you know. Which is fine and quite useful for bystanders trying to evaluate this debate on merit alone. I myself should repackage the section in this blog blog journal spot.com/2007/02/whats-wrong-with-for-loop.html”>oh, but wait, the traditional Bird-Merteens/Standard Prelude functions are kinda expressive too, you know. Which is fine and quite useful for bystanders trying to evaluate this debate on merit alone. I myself should repackage the section in this nadsat translator. Wikipedia pointed me to this page, where there is a translator for Windows. The very same page has the dictionary it uses, in the following form:

    A
    appy polly loggies : apologies :: School boy speak
    appy polly loggy : apology :: School boy speak
    B
    baboochka : old woman :: Russian (babooshka/grandmother)
    baboochkas : old women :: Russian (babooshka/grandmother)
    baddiwad : bad :: School boy speak
    baddiwadest : baddest :: School boy speak
    banda : band :: Russian (banda/band, gang)
    bandas : bands :: Russian (banda/band, gang)
    bezoomny : mad :: Russian (byezoomiyi/mad, insane)
    

    Yes, this probably can be handled with regexes as it’s regular enough, but that’s too complicated for me. I’m not smart enough for that finite automata stuff.

    So I copied all that text as-is and saved as nadsat.dict. Then I began writing the parser.

    module Nadsat where

    import Text.ParserCombinators.Parsec import qualified Data.Map as Map import Data.Char

    First thing I wanted was to weed out the “A”, “B”, etc. headers

    header = oneOf ['A'..'Z']

    Then I wrote a parser for one line of dictionary

    word = do { nadsat <- anyChar manyTill (char ‘:’); english <-anyChar manyTill (string “::”); etimology <- anyChar manyTill newline; return $ Map.singleton (filter isAlpha english) (filter isAlpha nadsat); }

    Given that, writing the parser for a whole dictionary is easy:

    dict = do { discard <- skipMany header; words <- many word; return $ Map.unions words; } The trickiest part (and it’s not really tricky) is this:

    nadsatDict = parseFromFile dict "nadsat.dict"

    The type of that function is nadsatDict :: IO (Either ParseError (Map.Map [Char] [Char])), because trying to parse a file might throw an error. Luckily, Either ParseError b is an instance of Functor, so fmap solves the problem of using that Map dictionary easily.

    Free counter and web stats