Qual é a diferença quando escrevo isso?
data Book = Book Int Int
versus
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
haskell
types
type-systems
newtype
ewggwegw
fonte
fonte
newtype Book = Book Int Int
não é válido. Você pode, no entanto, ternewtype Book = Book (Int, Int)
observado os dons abaixo.Respostas:
Ótima pergunta!
Existem várias diferenças importantes.
Representação
newtype
garante que seus dados tenham exatamente a mesma representação em tempo de execução, como o tipo que você agrupa.data
declara uma nova estrutura de dados em tempo de execução.Portanto, o ponto principal aqui é que a construção para o
newtype
é garantida para ser apagada no tempo de compilação.Exemplos:
data Book = Book Int Int
newtype Book = Book (Int, Int)
Observe como ele tem exatamente a mesma representação que um
(Int,Int)
, já que oBook
construtor é apagado.data Book = Book (Int, Int)
Tem um
Book
construtor adicional não presente no arquivonewtype
.data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
Sem ponteiros! Os dois
Int
campos são campos com tamanho de palavra sem caixa noBook
construtor.Tipos de dados algébricos
Devido a essa necessidade de apagar o construtor,
newtype
só funciona ao agrupar um tipo de dados com um único construtor . Não há noção de novos tipos "algébricos". Ou seja, você não pode escrever um novo tipo equivalente a, digamos,já que possui mais de um construtor. Nem você pode escrever
Rigor
O fato de o construtor ser apagado leva a algumas diferenças muito sutis no rigor entre
data
enewtype
. Em particular,data
introduz um tipo que é "elevado", significando, essencialmente, que ele tem uma maneira adicional de avaliar o valor mais baixo. Como não há construtor adicional em tempo de execuçãonewtype
, essa propriedade não é válida.Esse ponteiro extra no
Book
para(,)
construtor nos permite colocar um valor inferior em.Como resultado,
newtype
edata
possui propriedades de rigidez ligeiramente diferentes, conforme explicado no artigo da wiki Haskell .Desembalagem
Não faz sentido desmarcar os componentes de a
newtype
, pois não há construtor. Embora seja perfeitamente razoável escrever:produzindo um objeto de tempo de execução com um
T
construtor e umInt#
componente. Você só obter um nuInt
comnewtype
.Referências :
fonte
newtype
é apagado após a compilação e o tempo de execução usarem a mesma representação para tipos antigos e novos, como ainda podemos definir instâncias para os tipos antigo e novo? Como o tempo de execução pode entender qual instância usar?newtype
obviamente ainda não foram apagados.