Scusate se la domanda è molto elementare, sono ancora molto nuovo per Haskell. Diciamo che ho una funzione che può funzionare solo con due numeri che sono nella razione d'oro (1.618), come posso definire i tipi di myfunx y per prendere solo i numeri di rapporto aureo. Cosa succede se invoco myfun senza numeri golden ratio dal mio programma (un errore di compilazione?)? Cosa succede se la chiamata senza numeri golden ratio viene eseguita in runtime tramite l'input dell'utente?Utilizzo dei tipi di Haskell per sostituire le dichiarazioni di asserzione o se assegni in altre lingue
risposta
Si potrebbe desiderare un ADT che può essere costruito solo con i numeri con rapporto dorato, quindi scrivere myfun per accettare quel tipo di dati.
Ho assunto Intero come un tipo di base, ma è possibile utilizzarne altri (es: Double o Float) o persino essere polimorfico.
1) Effettuare l'ADT
module Golden (Gold, getGold, buildGold) where
data Gold = G Integer Integer
getGold :: Gold -> (Integer, Integer)
getGold (G x y) = (x, y)
buildGold :: Integer -> Integer -> Maybe Gold
buildGold x y
| isGolden x y = Just (G x y)
| otherwise = Nothing
Avviso questo modulo esporta il tipo Gold
ma non il costruttore (vale a dire, non G
). Quindi l'unico modo per ottenere un valore di tipo Gold
è con buildGold
che esegue un controllo in fase di esecuzione - ma solo uno - in modo che i valori di Gold possano essere utilizzati e si presumano essere un rapporto aureo da tutti i consumatori senza controllo.
2) Utilizzare l'ADT per costruire myfun
myfun :: Gold -> ???
myfun g = expr
where (x, y) = getGold g
Ora, se si tenta di chiamare myfun
con un numero non d'oro (un valore non di tipo Gold
) quindi si otterrà un errore di compilazione.
Recap Per creare numeri dorati è necessario utilizzare la funzione buildGold
, che forza il numero da controllare.
Avviso cosa viene controllato quando! Si dispone di una garanzia di compilazione che myfun
e tutte le altre funzioni che si desidera utilizzare con Gold
, vengono sempre fornite le percentuali d'oro. L'input del programma (da utente, rete o dove mai) richiede ancora i controlli di runtime ed è ciò che fornisce buildGold
; ovviamente non ci sarà mai un programma che possa promettere che l'umano non digiterà qualcosa di indesiderabile.
Anche le alternative fornite nei commenti alla tua domanda sono degne di considerazione.Un ADT è leggermente pesante se tutto ciò di cui hai bisogno è una singola funzione, myfun
, che può fallire e quindi avere solo myfun :: (Integer, Integer) -> Maybe ???
.
Il meglio che puoi fare praticamente è un controllo in fase di esecuzione. Potrebbero esserci alcuni calcoli a livello di codice che non conosco (vedi il commento di Luqui), ma questo non è pratico in Haskell.
Si potrebbe utilizzare an assert, che è ciò che si desidera sostituire,
checker :: a -> b -> Bool
checker x y = x * 1.618 `approxEqual` y
unsafeMyfun :: a -> b -> c
unsafeMyfun x y = assert (checker x y) (doRealThingWith a b)
o restituire un Maybe a
(o Either err a
) per evitare eccezioni che non possono essere catturati in funzioni pure,
myfun :: a -> b -> Maybe c
myfun x y = do
guard $ checker x y
return $ doRealThingWith x y
oppure utilizzare un tipo di contratto personalizzato come nella risposta di Tom, ecc. In alcun modo, non è possibile controllare il vincolo in fase di compilazione. Infatti, a causa della monade IO, qualsiasi vincolo in fase di compilazione non può essere preciso.
No, lui può fare molto meglio usando il sistema di tipi per assicurarsi che tutti i numeri con il minimo numero di oro vengano controllati prima di essere inviati a 'myfun'. –
Inoltre, è meglio non confrontare mai due numeri in virgola mobile per l'equivalenza esatta. – EFraim
@EFraim: Come commentato dall'OP, "Non farti coinvolgere da un cattivo esempio: se aiuta a immaginare xey sono un messaggio e hash salato ...", quindi non concentriamoci su di esso. – kennytm
La tecnica più semplice è utilizzare smart constructors, che utilizza una funzione da Int a GoldenInt, che controlla che i valori siano nei rapporti richiesti.
Con uno sforzo maggiore, è possibile utilizzare type level numbers per garantire che non sia necessario alcun controllo di runtime, tuttavia, dato che sei un principiante, mi attenersi al metodo del costruttore intelligente.
La risposta di Tom sopra è un esempio di questo idioma.
Il tipo aritmetico e la fine del collegamento dei costruttori intelligenti sono molto intelligenti (e il primo pezzo di codice che ho visto dal mio primo anno in CS che utilizza i numeri di Peano). Il tipo aritmetico può essere applicato a qualsiasi cosa o solo a una determinata "classe di conteggio" dei problemi? –
- 1. Utilizzo dei tipi di dati in Haskell
- 2. Haskell utilizzo tipi di dati buoni practise
- 3. Che cosa rende il sistema di tipi Haskell più "potente" rispetto ai sistemi di tipi di altre lingue?
- 4. Parametrizzazione dei tipi per interi in Haskell
- 5. StyleCop per altre lingue
- 6. esiste un'API per GIT (C++ o altre lingue)
- 7. Dichiarazioni di controllo in Haskell?
- 8. Esempi di backend ipython in altre lingue?
- 9. Se dichiarazioni
- 10. Moduli astratti alla scala in C# o in altre lingue?
- 11. Utilizzo dei tipi di funzione in Go
- 12. Pattern di utilizzo delle variabili di condizione in C/C++ e in altre lingue
- 13. Esempio di utilizzo di asserzione in Python?
- 14. Efficienza: Interruttore dichiarazioni sopra se le dichiarazioni
- 15. Qual è l'equivalente di Python Fabric in altre lingue?
- 16. Test automatizzati in RPG (o altre lingue ILE)
- 17. Ottenere lista dei paesi in altre lingue oltre all'inglese
- 18. Perché abbiamo bisogno di altre lingue JVM
- 19. Ruby On Rails: pluralize per altre lingue
- 20. Uso di "Forse" di Haskell, tipo dichiarazioni [domanda per principianti]
- 21. L'oggetto DataFrame dei panda ha sostituito le altre alternative per tipi di dati eterogenei?
- 22. Utilizzo di SwingEventMonitor per monitorare altre applicazioni?
- 23. Dichiarazioni di variabili che seguono se dichiarazioni
- 24. Ruby o altre lingue funzioneranno più velocemente con Parrot?
- 25. Sto abusando di "salvataggio" per assegni nulli?
- 26. Il dispositivo Duff funziona in altre lingue?
- 27. Invio di messaggi da altre lingue a un kernel IPython
- 28. Controllo Se poi le dichiarazioni in PHP
- 29. strumento Haskell per riscrivere le dichiarazioni di importazione di nominare tutte le importazioni?
- 30. Quali framework di elaborazione dei pagamenti, come ActiveMerchant, sono disponibili per altre lingue?
Perché sono necessari 2 parametri? – kennytm
Non si può avere la funzione accetta un argomento e si assume che l'altro numero sia 1,618 volte maggiore? –
Non è possibile applicarlo in fase di compilazione (con due parametri) - e, come si fa notare, non ci sarebbe alcuna protezione contro l'input dell'utente. * Ecco una contro-sfida * dati due numeri, xey, scrivi una funzione per restituire true sef formano la sezione aurea. Ora, modificalo per restituire un rapporto aureo o nulla, a seconda dei casi. –