2015-11-20 5 views
8

Dieser C-Code zu erzeugen kann konzeptionell als die Schaffung eines neuen Array identisch ist mit einer Eingangsanordnung beschrieben, aber mit 1 als dem ersten Element:Haskell: letzte Referenz auf eine Variable verwenden, um effizient eine neue Variable

int* retire_and_update(int* arr) { 
    arr[0] = 1; 
    return arr; 
} 

Diese ist eine reine Funktion (Wink Wink Nudge Nudge), solange keine weiteren Verweise auf das Eingangsarray und seine Elemente gemacht werden. Das C-System wird das für uns nicht durchsetzen, aber es scheint im Prinzip durchsetzbar zu sein.

Der Code, dass gcc erzeugt ist einfach und effizient:

retire_and_update: 
    movq %rdi, %rax 
    movl $1, (%rdi) 
    ret 

Unsere Funktion erreicht, das scheinbar Unmögliche durch eine ganz neue Array in konstanter Zeit und mit keinem zusätzlichen Speicher zu schaffen. Nett. Kann eine Haskell-Funktion mit Array-ähnlichen Ein- und Ausgaben geschrieben werden, die mit ähnlichem Code gültig implementiert werden könnten? Gibt es eine Möglichkeit, "das ist die letzte Referenz auf diese Variable" auszudrücken, so dass eine reine Funktion die Variable hinter den Kulissen kannibalisieren kann?

Wenn die Funktion inline wird, dann muss hier nichts Interessantes passieren. Nehmen wir an, der Aufrufer und die Funktion werden separat kompiliert.

+7

IIUC „Einzigartigkeit Arten“ oder ähnlich lineare Typen, dies zu tun. Leider sind diese nicht Bestandteil des Haskell-Typ-Systems. Der konventionelle Weg in Haskell besteht darin, [die ST-Monade] (https://hackage.haskell.org/package/base-4.8.0/docs/Control-Monad-ST.html) zu verwenden, um konzeptionell eine Mutation zu erreichen reine Einstellung (die vorübergehend in eine Monade mit veränderbarem Zustand eintritt, aber das Typsystem garantiert, dass die Berechnung deterministisch ist und der Zustand nicht leckt). Es ist eine ganz andere Sache als das, worüber du redest. – luqui

+3

[Clean] (http://clean.cs.ru.nl/Clean) ist eine funktionale Sprache mit Eindeutigkeitstypen, die ebenfalls von Haskell beeinflusst werden. – chi

Antwort

6

Obwohl ST monad ist nicht genau das, was Sie beschreiben, in der Praxis können Sie die meisten, dass STUArray mit implementieren. So kann ein Mock-up von Ihrem Code so etwas wie:

import Control.Monad (forM_) 
import Control.Monad.ST (ST) 
import Data.Array.Unboxed (UArray) 
import Data.Array.ST (STUArray, newArray, readArray, writeArray, runSTUArray) 

retire_and_update :: STUArray s Int Int -> ST s (STUArray s Int Int) 
retire_and_update arr = do 
    writeArray arr 0 1 
    return arr 

und wenn Sie eine andere Funktion, die die Anordnung an Ort und Stelle mutiert, wie:

mutate_inplace :: STUArray s Int Int -> Int -> ST s() 
mutate_inplace arr size = do 
    forM_ [2..size - 1] $ \i -> do 
     a <- readArray arr (i - 2) 
     b <- readArray arr (i - 1) 
     writeArray arr i (a + b) 

Sie können binden die beiden unreine Funktion zusammen und nennen sie in einer reinen Funktion mit runSTUArray:

run :: Int -> UArray Int Int 
run size = runSTUArray $ do 
    arr <- newArray (0, size - 1) 0 
    retire_and_update arr 
    mutate_inplace arr size 
    return arr 

beachten Sie, dass run rein bleibt, und die früheren Versionen des zurückgegebenen Arrays sind überall nicht durchgesickert:

\> run 8 
array (0,7) [(0,1),(1,0),(2,1),(3,1),(4,2),(5,3),(6,5),(7,8)] 
+0

Es war ein Jahr, aber diese Antwort kam mir gerade in den Sinn und ich wollte überprüfen, ob ich es verstanden habe, jetzt habe ich eine Frage. Warum genau sagst du "ST Monad" passt nicht ganz zu der Frage? Meinst du nur die zusätzliche Typisierung und konzeptuelle Angelegenheit, den Zustand in einer Monade zu halten? Oder muss die Implementierung irgendwo eine Kopie erstellen? Vielen Dank. – Praxeolitic

+0

@Praxeolitic Es gibt * nein * kopieren; ST-Monade (im Gegensatz zu [State Monad] (https://wiki.haskell.org/State_Monad)) mutiert tatsächlich an Ort und Stelle. Der Sinn von ST Monad ist, dass Mutationen im Typsystem _explicit_ werden. Aber es gibt keine Garantien, die ["Eindeutigkeitstyp"] (https://en.wikipedia.org/wiki/Uniqueness_type) bieten. –

Verwandte Themen