2016-06-10 5 views
1
test :: VM.MVector s Int -> Int 
    test x = runST $ do 
    a <- return x 
    VM.read a 0 -- Type error 

Ich versuche herauszufinden, wie man nicht alles in eine ST-Monade in einer einzigen Funktion steckt. Wenn ich versuchen würde, x zu ändern oder einen Wert von ihm zurückzugeben, würde sich der Compiler über den nicht übereinstimmenden Zustandsteil des veränderbaren Vektors beschweren.Wie ändere oder lese ich einen veränderbaren Vektor, der als Argument in einer Funktion übergeben wurde?

Wäre es in Haskell möglich, an veränderbaren Vektoren zu arbeiten, oder muss ich sie in die unveränderlichen Gegenstücke einfrieren, bevor ich etwas daran mache?

Bearbeiten:

Hier ist der eigentliche Fehler.

Couldn't match type `s1' with `s' 
    `s1' is a rigid type variable bound by 
     a type expected by the context: ST s1 Int at rjb.hs:17:12 
    `s' is a rigid type variable bound by 
     the type signature for test :: VM.MVector s Int -> Int 
     at rjb.hs:16:11 
Expected type: VM.MVector 
       (Control.Monad.Primitive.PrimState (ST s1)) Int 
    Actual type: VM.MVector s Int 
Relevant bindings include 
    a :: VM.MVector s Int (bound at rjb.hs:18:5) 
    x :: VM.MVector s Int (bound at rjb.hs:17:8) 
    test :: VM.MVector s Int -> Int (bound at rjb.hs:17:3) 
In the first argument of `VM.read', namely `a' 
In a stmt of a 'do' block: VM.read a 0 

Bearbeiten: Die folgende besteht Typüberprüfung.

test :: VM.MVector (Control.Monad.Primitive.PrimState IO) Int -> IO (Int) 
    test x = VM.read x 0 

Ich vermute, dass ich auch die x Vektor mutieren würde. So ...

+0

können Sie bitte den tatsächlichen Fehler hinzufügen? – Carsten

+0

'a <- return x' ist redundant. Das gibt dir einfach wieder 'x'. – melpomene

+0

@Carsten Der Fehler wurde hinzugefügt. –

Antwort

5

Sie brauchen wahrscheinlich ein Beispiel. Hier ist eine grundlegende kommentierte, aber ich bin sicher, Sie werden andere im Netz finden, wenn Sie ein wenig googeln.

import Control.Monad.ST 
import qualified Data.Vector.Mutable as VM 

-- This returns a reference to a vector, wrapped in the ST s monad. 
test :: ST s (VM.MVector s Int) 
test = do 
    v <- VM.new 10  -- create vector 
    VM.write v 3 2000 -- modify it 
    VM.write v 4 3000 
    x <- VM.read v 3  -- access it 
    VM.write v 4 (x+1) 
    return v    -- return it 

-- This instead returns a (wrapped) Int 
test2 :: ST s Int 
test2 = do 
    v <- test   -- call test, which performs the allocation 
    VM.read v 4   -- return v[4] 

-- This returns a plain pure Int value  
test3 :: Int 
test3 = runST test2 

Beachten Sie, dass runST x kann nur verwendet werden, wenn die Art der x ist die Polytyp ST s TT wo nicht der Typ, Variablen mit sich bringt s. So erreicht die ST-Monade referentielle Transparenz.

In einfacheren Worten bedeutet dies, dass jeder "Zeiger" auf zugewiesenen Speicher nie von runST zurückgegeben werden kann. Wenn runST zurückkehrt, kann jede Zuordnung von veränderbaren Dingen freigegeben werden. Eine typische ST s Berechnung führt runST nur am äußersten Ende durch, wenn es bereit ist, alle veränderbaren Daten wegzuwerfen und einen unveränderlichen Teil davon zu behalten. Im obigen Beispiel war der unveränderliche Teil das vierte Element (wie üblich von 0 ausgehend), was ein unveränderliches Int ist.

Wenn Sie mit ST s nicht vertraut sind, würde ich empfehlen Sie Vektoren für den Moment vergessen, und einige Übung zu tun mit STRef s Int (Verweise auf Int) und ST. Jede ST Anleitung würde ausreichen.

+0

Richtig, das ist, was ich gesucht habe. So sieht also die Typ-Signatur für die ST-Monade aus. Und der veränderbare Vektor und die ST-Monade haben denselben "s" -Typ. Eigentlich, was sind diese 's's in' ST s (VM.MVector s Int) soll das tun, abgesehen davon, dass ich nicht versehentlich den Vektor mutieren kann? –

+5

@MarkoGrdinic 's' ist ein Dummy-Typ, der alle" Zeiger tragenden "Dinge wie" STRef s Int "oder" MVector s Int "" vergiftet ". Sein Zweck ist es zu verhindern, dass Sie diese "Zeiger" von 'runST' zurückgeben, nichts anderes - es ist nur um dem Compiler zu beweisen, dass Sie nach den Regeln gespielt haben. – chi

+0

@chi IIRC Es soll auch verhindern, dass Sie ST-Aktionen, die auf separaten Speicherblöcken arbeiten, unsicher verschachteln. Sie können also nicht versuchen, auf einen Zeiger zu verweisen, der in Block 'foo' innerhalb von' bar' erstellt wurde, ohne zuerst alle 'foo' auszuführen. – semicolon

Verwandte Themen