2017-05-10 1 views
0

Ich habe mit einer Funktion gekämpft, die ein verschachteltes Tupel zurückgeben soll - speziell die Eingabe der Funktion gibt mir eine Menge Probleme. Eine vereinfachte Version ist unten:Wiederholung mit Tupeltypen

tupfnc :: ????? 
tupfnc [a] = (a,()) 
tupfnc (a:as) = (a,tupfnc as) 

Die Idee ist, in einer Liste von Elementen (zB [0,1,5,3]) und nisten sie in ein Tupel wie folgt zu übernehmen: (0, (1, (5, (3,())))).

Mein inital Gedanke war, wie so eine Erklärung zu gehen:

tupfnc :: [a] -> (a,b) 

jedoch die dritte Zeile (in diesem Beispiel) wirft der Fehler

Solver.hs:56:17: error: 
    • Couldn't match expected type ‘(a, b)’ 
        with actual type ‘[(a, (a, b0))]’ 
    • In the expression: [(a, tupfnc as)] 
     In an equation for ‘tupfnc’: tupfnc (a : as) = [(a, tupfnc as)] 
    • Relevant bindings include 
     as :: [a] 
     a :: a 
     tupfnc :: [a] -> (a, b) 

Irgendwelche Vorschläge?

+3

Es gibt hier mehrere Dinge aus. Zuallererst enthält Ihr "Array" (welches eine Liste ist) immer den Typ _same_. Sie können nicht [0,1, a ', 3] 'haben, da'' a'' kein 'Int' ist. Als Nächstes geben Sie eine Liste oder ein Tupel zurück, aber ihre Typen unterscheiden sich, so dass dies auch nicht möglich ist. Und zu guter Letzt unterscheiden sich die Typen "(a, b)" und "(a, (a, b))", außer "b ~ (a, b)" und daher unendlich. Sie müssten ein 'data InPair a = Stop | verwenden InPair a (InPair a) 'um das zu erstellen, aber jetzt bist du zurück auf einer Liste. Suchen Sie nach inhomogenen Listen auf Typenebene? – Zeta

+0

Mein schlechter, mein Kopf war nicht gerade, wenn ich die Frage schrieb. Ich habe es bearbeitet, um korrekter zu sein. Die Elemente der Liste sollen alle vom selben Typ sein. Dein Kommentar zu b ~ (a, b) war mehr, wohin ich schaute. Ich weiß nicht, wie man eine Funktion definiert, die einen unendlichen Typ zurückgibt (ist das, wie sie heißen?). Ich werde mir auch inhomogene Listen auf Typenebene ansehen. –

+1

Auch bei der Bearbeitung geben Sie immer noch '(a,())' und '[(a, ...)]' zurück. Sie geben eine Liste oder ein Tupel zurück, aber das sind verschiedene Typen. Dies scheint ein XY-Problem zu sein. Was möchtest du eigentlich machen? – Zeta

Antwort

1

Dies ist nicht möglich, es sei denn, Sie verfügen über Informationen auf Typenebene über die Länge der Liste. Imagining eine Variante von Listen Vector in denen genannt, dass, wenn der Fall, können Sie folgendes tun können:

{-# LANGUAGE GADTs, PolyKinds, DataKinds, TypeFamilies, TypeOperators #-} 

-- | Peano natural numbers 
data Nat = Z | S Nat 

-- Just for convenience... 
type N0 = Z 
type N1 = S N0 
type N2 = S N1 
type N3 = S N2 
type N4 = S N3 
type N5 = S N4 
type N6 = S N5 
type N7 = S N6 
type N8 = S N7 
type N9 = S N8 

-- | Equivalent to a list, but carries information about its length with it 
data Vector (n :: Nat) a where 
    Nil :: Vector Z a 
    (:-) :: a -> Vector n a -> Vector (S n) a 

infixr 5 :- 

Jetzt können wir eine Art Familie definieren, die eine Zahl in ihre entsprechende verschachtelte Tupel konvertiert:

type family NestedTuple (n :: Nat) (a :: *) where 
    NestedTuple Z  a =() 
    NestedTuple (S n) a = (a, NestedTuple n a) 

Und schließlich können wir eine Funktion definieren, die Vector n a in ihre verschachtelte Tupelform konvertiert.

toList :: Vector n a -> NestedTuple n a 
toList Nil =() 
toList (x :- xs) = (x, toList xs) 

Sie können dies testen bei GHCi out:

ghci> :set -XFlexibleContexts 
ghci> toList ("foo" :- "bar" :- "baz" :- Nil) 
("foo",("bar",("baz",())))