digite para representar uma lista com 0 a 5 valores
14
Eu tenho um exercício em que tenho que definir um tipo para representar uma lista com 0 a 5 valores. Primeiro, pensei que poderia resolver isso recursivamente assim:
data List a = Nil | Content a (List a)
Mas não acho que essa seja a abordagem correta. Você pode, por favor, me dar um pensamento?
Não responderei seu exercício para você - para exercícios, é melhor descobrir a resposta você mesmo - mas aqui está uma dica que deve levá-lo à resposta: você pode definir uma lista com 0 a 2 elementos como
data List a = None | One a | Two a a
Agora, pense em como você pode estender isso para cinco elementos.
Bem, uma solução recursiva é certamente a coisa normal e de fato agradável em Haskell, mas é um pouco complicado limitar o número de elementos. Portanto, para uma solução simples para o problema, primeiro considere a estúpida, mas funcional, dada por bradm.
Com a solução recursiva, o truque é passar uma variável "counter" para baixo na recursão e desabilitar a adição de mais elementos quando você atingir o máximo permitido. Isso pode ser feito bem com um GADT:
{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeInType, StandaloneDeriving #-}import Data.Kind
import GHC.TypeLits
infixr5:#data ListMax :: Nat -> Type -> Type where
Nil :: ListMax n a
(:#):: a -> ListMax n a -> ListMax (n+1) a
derivinginstance(Show a)=> Show (ListMax n a)
Então
*Main>0:#1:#2:#Nil :: ListMax 5 Int
0:#(1:#(2:# Nil))*Main>0:#1:#2:#3:#4:#5:#6:#Nil :: ListMax 5 Int
<interactive>:13:16: error:• Couldn't match type‘1’ with ‘0’
Expected type: ListMax 0 Int
Actual type: ListMax (0+1) Int
• In the second argument of‘(:#)’, namely ‘5:#6:# Nil’
In the second argument of‘(:#)’, namely ‘4:#5:#6:# Nil’
In the second argument of‘(:#)’, namely ‘3:#4:#5:#6:# Nil’
Muito obrigado. Por ser um exercício para iniciantes, acho que é a abordagem mais fácil. Mas vou pensar na sua abordagem também.
mayerph 29/04
7
Por uma questão de integridade, deixe-me acrescentar uma abordagem alternativa "feia", que é, no entanto, bastante básica.
Lembre-se de que Maybe aé um tipo cujos valores são da forma Nothingou Just xpara alguns x :: a.
Portanto, reinterpretando os valores acima, podemos considerar Maybe aum "tipo de lista restrito", onde as listas podem ter zero ou um elemento.
Agora, (a, Maybe a)basta adicionar mais um elemento, portanto, é um "tipo de lista" onde as listas podem ter um ( (x1, Nothing)) ou dois ( (x1, Just x2)) elementos.
Portanto, Maybe (a, Maybe a)é um "tipo de lista" em que as listas podem ter zero ( Nothing), um ( Just (x1, Nothing)) ou dois ( (Just (x1, Just x2)) elementos.
Agora você deve entender como proceder. Quero enfatizar novamente que essa não é uma solução conveniente de usar, mas é um bom exercício para entendê-la (IMO).
Usando alguns recursos avançados do Haskell, podemos generalizar o acima usando uma família de tipos:
type family List (n :: Nat)(a :: Type):: Type where
List 0 a =()
List n a = Maybe (a, List (n-1) a)
Esta resposta pode ser estendida com a família de tipos da lista baseada em Talvez do comprimento máximo n .
leftaroundabout 30/04
@leftaroundabout Feito. Isso pode ser um pouco demais para um iniciante, mas eu adicionei mesmo assim.
chi
no máximo três asegundos em Either () (a, Either () (a, Either () (a, Either () ())))... álgebra de tipo interessante foldr (.) id (replicate 3 $ ([0] ++) . liftA2 (+) [1]) $ [0] == [0,1,2,3],.
Por uma questão de integridade, deixe-me acrescentar uma abordagem alternativa "feia", que é, no entanto, bastante básica.
Lembre-se de que
Maybe a
é um tipo cujos valores são da formaNothing
ouJust x
para algunsx :: a
.Portanto, reinterpretando os valores acima, podemos considerar
Maybe a
um "tipo de lista restrito", onde as listas podem ter zero ou um elemento.Agora,
(a, Maybe a)
basta adicionar mais um elemento, portanto, é um "tipo de lista" onde as listas podem ter um ((x1, Nothing)
) ou dois ((x1, Just x2)
) elementos.Portanto,
Maybe (a, Maybe a)
é um "tipo de lista" em que as listas podem ter zero (Nothing
), um (Just (x1, Nothing)
) ou dois ((Just (x1, Just x2)
) elementos.Agora você deve entender como proceder. Quero enfatizar novamente que essa não é uma solução conveniente de usar, mas é um bom exercício para entendê-la (IMO).
Usando alguns recursos avançados do Haskell, podemos generalizar o acima usando uma família de tipos:
fonte
a
segundos emEither () (a, Either () (a, Either () (a, Either () ())))
... álgebra de tipo interessantefoldr (.) id (replicate 3 $ ([0] ++) . liftA2 (+) [1]) $ [0] == [0,1,2,3]
,.