2010-12-09

read :: Read a =>

(continuando…)

show usando show usando show

Mas como é que obtemos as representações textuais das instruções?

Muito simples! Usamos a classe Show!

Mas para isso temos de instanciar Show para BFCommand, definindo show :: BFCommand –> String:

instance Show BFCommand where
show = undefined

Para já vamos deixar assim e acabar de definir show :: BF –> String.

Podemos então agora usar show em valores do tipo BFCommand (apesar de isso ainda não fazer nada interessante):

    show (BF (h:t)) = show h ++ -- ?

Assim já temos a representação da cabeça. Como fazemos para o resto da lista? Invocamos show recursivamente!

show (BF (h:t)) = show h ++ show t -- Não dá!

Pois, mas isto não é bem o que queremos! t é uma lista de BFCommand. Se fizermos show dessa lista vamos ter algo assim:

> show [DecVal, IncPtr, IncVal, DecPtr]
[-,>,+,<]

Existe uma instância de Show para listas, que coloca as representações dos seus elementos entre parentesis rectos, separados por vírgulas! Ora os parentesis rectos e as vírgulas têm ambos significados especiais em brainfuck. Não podemos chamar a instância de show para listas (show :: Show a => [a] –> String). Temos de chamar a instância de show para sequências de comandos brainfuck. Para isso vamos transformar a lista que é a cauda num BF, com uma função :: [BFCommand] –> BF. Essa função já existe:

> :t BF
BF :: [BFCommand] -> BF

O constructor BF faz exactamente o que queremos. Basta então chamá-lo previamente:

    show (BF (h:t)) = show h ++ show (BF t)

Agora há que reparar que, embora haja duas invocações de show, apenas a segunda é uma chamada recursiva. Isto porque as duas invocações são para instâncias diferentes de show. A primeira invoca show para BFCommands, ou seja, show :: BFCommand –> String. A segunda invoca show para BFs, ou seja, show :: BF –> String. Isto porque tanto BF como BFCommand são instâncias de Show.

Bem, BFCommand ainda precisa de algum trabalho… As primeiras seis instruções são simples, basta usar pattern matching:

instance Show BFCommand where
show IncPtr = ">"
show DecPtr = "<"
show IncVal = "+"
show DecVal = "-"
show Read = ","
show Print = "."
show (While bf) = -- ?

E agora o While. Antes de mais, de que tipo será bf?

> :t While
While :: BF -> BFCommand

Hmmm se While recebe um valor do tipo BF, então bf :: BF. Vamos então necessitar de colocar a representação textual de um BF entre parentesis rectos, usando… show :: BF –> String

    show (While bf) = "[" ++ (show bf) ++ "]"

Pois, então esta função show :: BFCommand –> String, invoca a show :: BF –> String, e essa por sua vez invoca show :: BFCommand –> String! Afinal ambas as invocações que tinhamos acima são recursivas!

    show (BF (h:t)) = show h ++ show (BF t) -- são ambas recursivas!

(continua…)

1 commentários:

Anónimo disse...

Hello colleagues, how is everything, and what you want to say regarding this post, in my view its truly amazing in favor of me.


Review my webpage best cellulite treatment

Enviar um comentário