2015-05-30 7 views
5

Dies ist eine Coding-Stil-Frage und nicht eine technische Frage.Namenskonflikt zwischen Feldwerten und lokalem Gültigkeitsbereich in Haskell

Ich habe häufig ein Problem festgestellt, bei dem ich Haskell (weniger als optimal) Datensatzsyntax (oder Objektive, das Problem endet die gleiche), um einen data Typ zu erstellen. Ich lande mit Feldzugriffsfunktionen, die nach meinen Feldern benannt sind. Als gewissenhafter Programmierer versuche ich, meine Feldnamen sinnvoll zu machen.

Irgendwann später muss ich ein Feld aus meinem Typ und behalten Sie seinen Wert in einer lokalen Variablen. Dies geschieht oft innerhalb eines StateMonad in einem do Block. Die Frage ist, wie ich die lokale Variable nenne. Der offensichtlichste Name wird bereits als Feldzugriffsgerät verwendet. Ich finde mich selbst mit Abkürzungen, die dazu neigen, meinen Code weniger lesbar zu machen.

Gibt es eine Haskell-Codierungskonvention, die dieses Problem löst?

Beispiel

data Qaax = Qaax { 
     foo :: SomeFoo 
    , bar :: SomeBar 
    , ... 
    } 

baz :: (MonadState Qaax m) => (...) -> m() 
baz (...) = do 
    f <- gets foo -- I'd really like to use something more descriptive then 
       -- `f` but `foo` is already taken. 
    ... 
    return() 

Antwort

3

Das Hinzufügen von 'als Suffix ist eine etablierte Konvention zur Bildung unterschiedlicher, aber verwandter Namen. Ein Schlüsselbeispiel ist foldl und foldl'.

In exportierten Namen wie foldl' ist es in der Regel eine gute Idee, ein konsistentes Thema für das, was die 'bedeutet für Ihre Bibliothek (oft ist es "strengere Version von", wie in foldl'). Aber in lokalen Namen können Sie viel freier sein, es einfach zu verwenden "eine andere eng verwandte Sache, die ich gerne den gleichen Namen wie hätte".

Der Nachteil ist, dass es nicht sehr deutlich ist, so kann es Lesbarkeit verletzen; vor allem, wenn Sie beide Versionen gemeinsam verwenden müssen. Und wenn Sie feststellen, dass Sie foo''' benötigen, sollten Sie wahrscheinlich über ein anderes Namensschema nachdenken!

2

Die NamedFieldPuns Erweiterung dabei helfen kann. Beim Pattern-Matching auf einem Datensatz, eine Variable mit dem gleichen Namen wie ein Datensatzfeld bindet:

{-# LANGUAGE NamedFieldPuns #-} 

baz :: (MonadState Qaax m) => m() 
baz = do 
    Qaax {foo} <- get 
    return() 

Ein mögliches Problem besteht darin, dass die Zugriffseinrichtung für den Rest des Blockes do abgeschattet wird.

Verwandte Themen