2016-05-04 11 views
0

Sorry für die Frage als möglicherweise dumme Frage, aber zurück zu Haskell, um einige Konvertierung von einem Datenbank-Paket zu einem anderen zu tun, finde ich mich ein wenig verwirrt darüber, wie man das richtig macht.Funktion mit Typ-Synonym

Im Database.SQLite3 Modul gibt es eine execWithCallback mit Typ

execWithCallback :: Database -> Text -> ExecCallback -> IO() 

Nun wird der Rückruf als

type ExecCallback = ColumnCount -> [Text]-> [Maybe Text] -> IO() 

definiert ist, die eine Funktion mit dem Typ ist, ExecCallback Meine dumme Testcode kompiliert und läuft korrekt:

{-# LANGUAGE OverloadedStrings #-} 

import Database.SQLite3 
import Data.Text 

cb :: ColumnCount -> [Text] -> [Maybe Text] -> IO() 
cb n cnl ct = do print $ cnl !! 1 
        return() 

main = do 
    dh <- open "fileinfo.sqlite" 
    execWithCallback dh "select * from files;" cb 
    close dh 

aber dann, was ist der Sinn des Typs ??? Und, wie kann ich angeben, dass cb ein ExecCallback ??

+2

Es kann Typ Signaturen kürzer machen !!! Und Sie müssen nicht angeben, dass es eins ist. es ist einfach !! Aber wenn Sie möchten, können Sie 'cb :: ExecCallback' schreiben. Ich würde es jedoch nicht besonders empfehlen; es zu schreiben macht es klarer. Und Sie brauchen nicht so viele Fragezeichen! – dfeuer

Antwort

2

In Haskell, mit type definieren Sie ein Typ Synonym. In Ihrem Beispiel bedeutet das, dass ExecCallback nur ein Alias ​​für den Typ ColumnCount -> [Text]-> [Maybe Text] -> IO() ist, sie sind austauschbar.

Sie könnten die folgenden Zeilen

ändern
cb :: ColumnCount -> [Text] -> [Maybe Text] -> IO() 
cb n cnl ct = do print $ cnl !! 1 
        return() 

zu

cb :: ExecCallback 
cb n cnl ct = do print $ cnl !! 1 
        return() 

und alles funktionieren würde, noch wie es ist. Es kann Ihren Code kürzer und lesbarer machen.

Ein weiteres gutes Beispiel ist

type String = [Char] 

in Prelude. Ich wette, dass Sie normalerweise String anstelle von [Char] in den meisten Fällen verwenden. Aber Sie können auch absolut frei sein.

Weitere (völlig unabhängig) Beispiel ist die conduit Paket, in dem einige type synonyms einen großen Unterschied machen:

type Sink i = ConduitM i Void 
type Consumer i m r = forall o. ConduitM i o m r 

Für etwas, das für Werte von jeder Art ein Waschbecken ist i, Sink i scheint Art und Weise besser lesbar als ConduitM i Void. Das Gleiche gilt für Consumer.

+0

Ein anderes gutes Beispiel ist "Linse", die super-gnarly Synonyme hat. Eine der einfachsten ist "Typ Lens s t a b = forall f. Funktor f => (a -> f b) -> s -> f t '. – dfeuer

+0

@dfeuer ok, ich bin mir sicher, dass es da seltsame Synonyme gibt, aber ich bin froh, dass ich gelernt habe, wie man diesen einfachen Fall unterstützt :-) Wie auch immer, danke! –