2015-08-16 3 views
6

hier ein Sonderfall der allgemeinen Frage ist ich wirklich fragen: Angenommen, ich in einem leistungskritischen Code-Abschnitt bin, und ich habe einen WertHaskell/GHC: Konstruktor nicht sicher dekonstruieren?

x :: Maybe Int 

Ich weiß, es ist ein Just Int und kein Nothing erhalten , aber aufgrund Code aus meiner Kontrolle, kann ich nicht arrangieren, um die tatsächliche Int direkt zu erhalten. Ich möchte

case x of 
    Just i -> whatever i 

tun, aber ich möchte nicht GHC jede Überprüfung oder Fehlerbehandlung oder Sprünge oder irgendetwas einfügen; interpretiere die Bits einfach so, als wären sie in der Form Just i und lass mich mit den Konsequenzen umgehen.

Ist das möglich? (Ja, ich weiß, das ist etwas, das man nicht regelmäßig tun sollte.)

+5

Vielleicht spielen einige hässliche Tricks mit 'unsafeCoerce' und unter einer großen Annahme, wie GHC präzise implementiert seine Laufzeit können Sie dies erreichen. Aber...Ich bezweifle wirklich, dass diese Kontrolle ein großes Problem ist: Haben Sie Beweise dafür? Wie Knuth es ausdrückt, ist vorzeitige Optimierung die Wurzel allen Übels. Und benutzen Sie nicht 'unsichere * Sachen, es sei denn, Sie können wirklich, wirklich nicht ohne tun. – chi

+0

Nein, ich habe keine Beweise, und ich werde ein Benchmarking durchführen, bevor ich irgendetwas umsetze. –

+5

Haben Sie sich den kompilierten Core angesehen, den Ihr Programm generiert? Je nachdem, warum ein "Maybe" an erster Stelle steht, ist es * möglich *, dass GHC es vielleicht schon für dich entfernt hat ... – MathematicalOrchid

Antwort

1

Manchmal können Sie GHC helfen herauszufinden, dass eine GADT-Musterübereinstimmung insgesamt ist, indem Sie einige Mustersignaturen hinzufügen. Ich bin mir nicht wirklich sicher, warum das manchmal hilft, aber es kann. Wenn Sie wirklich unsicher sein möchten, besteht die Möglichkeit darin, ein informativeres GADT als das, mit dem Sie arbeiten, zu erstellen und unsichere dazu zu zwingen. So etwas wie dieses:

data Shmaybe :: Bool -> * -> * where 
    Noway :: Shmaybe r a 
    Shucks :: a -> Shmaybe True a 

fromShucks :: ShMaybe True a -> a 
fromShucks (Shucks a) = a 

unsafeFromJust :: forall a . Maybe a -> a 
unsafeFromJust m = fromShucks (unsafeCoerce m :: Shmaybe True a) 

Es ist wichtig, dass die Konstruktoren in beiden Argumenttypen und Reihenfolge übereinstimmen. Natürlich ist das alles absurd unsicher und kommt ohne Garantien aus. Segmentierungsfehler können auftreten.

1

Betrachten Sie den YOLO typeclass https://gist.github.com/nkpart/8922083d3c18a8f777b8

instance Yolo Maybe where 
    yolo (Just x) = x 

N. B mit: Das war ein Witz. Verwenden Sie .

+0

'fromJust' enthält einen Check für' Nothing', was ich vermeiden wollte. –

+1

Dann vielleicht 'Yolo' verwenden – Arnon

1

Ich kenne mehrere Möglichkeiten, aber alle enthalten implizit Code für werfen Fehler im Nothing Fall.

Irrefutable Muster:

λ> let Just a = Just "hi" 
λ> a 
"hi" 
λ> let Just a = Nothing 
λ> a 
*** Exception: <interactive>:4:5-20: Irrefutable pattern failed for pattern Data.Maybe.Just a 

Nicht exhastive Muster:

λ> let f (Just a) = a 
λ> f (Just "hi") 
"hi" 
λ> f Nothing 
*** Exception: <interactive>:6:5-18: Non-exhaustive patterns in function f 

fromJust (überprüfen und werfen Fehler):

λ> fromJust (Just "hi") 
"hi" 
λ> fromJust Nothing 
*** Exception: Maybe.fromJust: Nothing 

Sie können nichtverwendenweil für alle a die internen Darstellungen von Maybe a und a sind unterschiedlich, und ich bin nicht bewusst, eine Möglichkeit, GHC die anderen Fälle in ein unwiderlegbares Muster nicht zu überprüfen.

Haben Sie gezeigt, dass dieses Verhalten unerwünschte Leistungsmerkmale hat und dass es keine anderen andere, leichtere Optimierungen gibt? Wenn Sie nicht haben, würde ich mich nicht um es kümmern :)