Parece que qualquer instância vinculada deve ter uma implementação sã do Enum. Pessoalmente, não consigo pensar em um contra-exemplo, embora, se alguém criar um que não seja patológico, entenderei por que não é esse o caso.
Ao executar :i
nas duas classes de tipos, parece que a única exceção atualmente na biblioteca padrão é para tuplas, que são limitadas, mas não enums. No entanto, qualquer tupla limitada também deve ser enumerável de maneira sã, simplesmente incrementando o último elemento e, em seguida, contornando quando se trata de maxBound.
Essa alteração provavelmente envolveria também a adição predB
e / nextB
ou algo parecido a Bounded, para uma maneira segura / em loop de percorrer os valores de Enum. Nesse caso, toEnum 0 :: (...)
seria igual a(toEnum 0, toEnum 0, ...) :: (...)
Double
/Float
e todos os tipos similares implementados deEnum
qualquer maneira, eles apenas produzemsucc = (+ 1)
efromEnum = truncate
. O jeito de Haskell, na verdade, faz sentido do ponto de vista da praticidade, caso contrário [0, 0,5 ..] e similares não funcionariam, então parece que Haskell não se preocupa com a responsabilidade quando se trata de Enums.succ
é(+1)
. Isso é estranho, porqueDouble
eFloat
não tem precisão infinita e, portanto, é enumerável -succ
poderia ter sido definido como +1 ULP .Respostas:
Um exemplo prático que eu gosto vem do mundo das linguagens de programação: o conjunto de tipos em um sistema OO é limitado e discreto, mas não enumerável, e parcialmente ordenado, mas não totalmente ordenado.
A ordem parcial em questão é a relação de subtipagem
<:
. O limite superior seria então o tipo superior (que C # chamaobject
e Scala chamaAny
), e o limite inferior seria o tipo inferior (ScalaNothing
; C # / Java não tem equivalente para falar).No entanto, não há como enumerar todos os tipos no sistema de tipos, portanto você não pode escrever um
instance Enum Type
. Isso deve ficar claro: os usuários podem escrever seus próprios tipos, para que não haja como saber com antecedência. Você pode enumerar todos os tipos em qualquer programa, mas não em todo o sistema.Da mesma forma, (de acordo com uma certa definição razoável de subtipagem),
<:
é reflexivo, transitivo e anti-simétrico, mas não total . Existem pares de tipos que não são relacionados<:
. (Cat
eDog
são ambos subtipos deAnimal
, mas nenhum é um subtipo do outro.)Suponha que estamos escrevendo um compilador para uma linguagem OO simples. Aqui está a representação dos tipos em nosso sistema:
E a definição da relação de subtipagem:
Isso também nos dá uma relação de super tipagem.
Você também pode encontrar o limite superior mínimo de dois tipos,
Exercício: mostre que
Type
forma um poset completo delimitado de duas maneiras, abaixo<:
e abaixo>:
.fonte
x == y = x <= y && y <= x
. Se eu estivesse projetando umaPoset
classe, teriaclass Eq a => Poset a
. Um rápido Google confirma que outras pessoas tiveram a mesma ideia .data Bound a = Min | Val a | Max
qual aumenta um tipoa
com+∞
e-∞
elementos. Por construçãoBound a
pode ser feita sempre uma instânciaBounded
, mas ele só estaria equatable se o tipo subjacentea
éDouble
, ondeconst (1/0)
émaxBound
econst (negate 1/0)
é,minBound
mas\x -> 1 - x
e\x -> x - 1
são incomparáveis.É porque as operações são independentes, portanto, vinculá-las a um relacionamento de subclasse não compram nada para você. Digamos que você desejasse criar um tipo personalizado implementado
Bounded
, talvezDoubles
restrito entre um máximo e um mínimo, mas você não precisou de nenhuma dasEnum
operações. SeBounded
fosse uma subclasse, você teria que implementar todas asEnum
funções de qualquer maneira, apenas para compilar.Realmente não importa se existe uma implementação razoável para
Enum
, ou qualquer outro número de classes de tipo. Se você realmente não precisa, não deve ser forçado a implementá-lo.Compare isso com dizer,
Ord
eEq
. Lá, asOrd
operações dependemEq
delas, portanto, faz sentido exigir que a subclasse evite duplicação e garanta consistência.fonte
Bounded
diz "Ord não é uma superclasse de Bounded, pois tipos que não são totalmente ordenados também podem ter limites superior e inferior".<:
para é um subtipo de ,∀ T S. T <: S ∨ S <: T
não é válido (por exemplo,int !<: bool ∧ bool !<: int
). Você provavelmente enfrentaria isso se estivesse escrevendo um compilador.