2011-01-22 9 views
5

Quindi, ho una funzione con più definizioni (guardie) e, a seconda di quale corrisponde, sto cercando di avere o restituire un (a, b) o [ (a, b)], tuttavia il compilatore genera errori perché sono di tipi diversi. Stavo cercando di usare Either per risolvere questo problema, ma probabilmente non lo usavo nel modo giusto: P. qualsiasi aiuto?Come ottenere una funzione per restituire diversi tipi

+1

Non è possibile farlo direttamente perché il tipo di ritorno della funzione deve essere noto al momento della compilazione, mentre le guardie sono abbinate in fase di esecuzione. Ma sei sicuro di voler davvero restituire un tipo diverso? Se si intende abbinare il risultato sul risultato per distinguere i due casi, o va bene. O forse una lista di singleton funzionerà nel primo caso? Puoi fornire maggiori dettagli su ciò che farai? – b0fh

+0

http://paste.pocoo.org/show/325066/ è la mia funzione fino ad ora –

+0

che è come leggere un incantesimo. Cosa dovrebbe significare? – luqui

risposta

9

Either - o un tipo di dati personalizzato equivalente ad esso - è l'unico modo per farlo. Ecco un esempio stupido:

stuff :: Int -> Either (Int,Int) [(Int,Int)] 
stuff 0 = Left (0, 0) 
stuff n = Right [ (x,x) | x <- [0..n] ] 

Poi, quando qualcuno chiama questa funzione, possono pattern match per scoprire quale dei due tipi tornò:

foo n = case stuff n of 
      Left (a,b) -> ... 
      Right pairs -> ... 

Tuttavia, senza sapere nulla circa il tuo problema, in In generale, consiglierei di pensare un po 'di più al significato della vostra funzione. Che cosa prende, cosa restituisce? Sii preciso, matematico. Più semplice è la risposta, più agevolmente questa funzione funzionerà con il resto del programma e con i concetti di Haskell. Per me, in tali descrizioni, raramente si presenta Either. Come puoi unificare i due risultati? Forse hai appena restituito la lista singleton [(a,b)] invece di Left (a,b), se questo ha senso per la tua funzione.

Haskell non funziona bene con funzioni che cercano di essere troppo intelligenti, il tipo a cui potresti essere abituato da Python o jQuery. Mantienilo stupido e preciso: ottieni la tua complessità dal componendo questi semplici pezzi. Se sei curioso di questo, fai un'altra domanda con maggiori dettagli sul tuo problema, su cosa stai cercando di realizzare e perché vuoi che funzioni in questo modo. Scusa per la predica :-)

+0

Permettetemi di aggiungere che la proprietà che vogliamo del sistema di tipi è quella di * preservation *: In senso lato se abbiamo il tipo 'stuff :: Int -> (Int, Int) 'quindi una chiamata a' stuff 7 'dire ridurrebbe a '[(x, x) | x <- [0..n] 'nell'esempio che ha tipo' [(Int, Int)] '. Questo è diverso dal tipo di ritorno proclamato di 'stuff' e quindi il tipo non sarebbe conservato.Se dobbiamo fidarci del sistema dei tipi per qualsiasi cosa, questa discrepanza deve essere esclusa. Quindi il controllo del tipo rifiuta il nostro programma come mal digitato. –

0

Le funzioni in Haskell possono restituire solo un tipo, quindi o funzioneranno per voi poiché la funzione restituirà il tipo E (a, b) [(a.b)].

Non sono sicuro di cosa è andato storto con il modo che si sta utilizzando, ma qui è un semplice esempio del suo utilizzo:

test a b = 
    if a == True 
    then Left (a,b) 
    else Right [(a,b)] 
+0

quindi ecco la mia funzione ora: http://paste.pocoo.org/show/325090/ ecco l'errore: http: //paste.pocoo. org/show/325093/ –

+0

@Chris 'Right lgst i' dovrebbe essere' Right (lgst i) '. – dave4420

+0

ok così http://paste.pocoo.org/show/325143/ funziona, tuttavia le ultime due guardie hanno bisogno di guardare qualcosa come http://paste.pocoo.org/show/325144/ che mi dà: http://paste.pocoo.org/show/325145/ –

Problemi correlati