ho un gran numero di in luogo vector funzioni del tipoScoping per le variabili di tipo temporaneo
f :: (M.MVector v r, PrimMonad m) =>
v (PrimState m) r -> v (PrimState m) r -> m()
Queste funzioni lavorano soprattutto sul posto, quindi è conveniente avere loro tesi essere un vettore mutevole in modo che Posso comporre, iterare, ecc. Tuttavia, al livello più alto, voglio solo lavorare con immutabili "Haskell"/pure vettori.
Ecco un esempio del problema:
{-# LANGUAGE TypeFamilies,
ScopedTypeVariables,
MultiParamTypeClasses,
FlexibleInstances #-}
import Data.Vector.Generic as V hiding (eq)
import Data.Vector.Generic.Mutable as M
import Control.Monad.ST
import Control.Monad.Primitive
f :: (M.MVector v r, PrimMonad m) =>
v (PrimState m) r -> v (PrimState m) r -> m()
f vIn vOut = do val <- M.read vIn 0
M.write vOut 0 val
applyFunc :: (M.MVector v r, PrimMonad m, V.Vector v' r, v ~ Mutable v') =>
(v (PrimState m) r -> v (PrimState m) r -> m()) -> v' r -> v' r
applyFunc g x = runST $ do
y <- V.thaw x
g y y -- LINE 1
V.unsafeFreeze y
topLevelFun :: (V.Vector v r) => r -> v r
topLevelFun a =
let x = V.replicate 10 a
in applyFunc f x -- LINE 2
Il codice come risultati scritti in un errore sulla linea 1:
Could not deduce (m ~ ST s)
Expected type: ST s()
Actual type: m()
in the return type of g, LINE 1
commentare la linea 1 genera l'errore sulla linea 2:
Ambiguous type variable `m0' in the constraint:
(PrimMonad m0) arising from a use of `applyFun'
Ho provato una varietà di digitazione esplicita (utilizzando ScopedTypeVariables, foral esplicito ls, ecc.) ma non ho trovato un modo per correggere il primo errore. Per l'errore LINE 1, sembra che m
debba essere semplicemente considerato come ST s
poiché sono in un runST
.
Per l'errore di linea 2 (linea 1 commentato), l'unica cosa che mi è venuta in mente che funziona è
class Fake m v where
kindSig :: m a -> v b c
instance Fake m v
topLevelFun :: forall m v v' r . (V.Vector v' r, M.MVector v r, PrimMonad m, Fake m v, v ~ Mutable v') => r -> v' r
topLevelFun a =
let x = V.replicate 10 a
in applyFunc (f::Transform m v r) x -- LINE 2
che è ovviamente insoddisfacente: devo creare una classe falso, con un metodo ancora più inutile il cui unico compito è dimostrare i tipi di argomenti della classe. Quindi creo un'istanza generica per tutto in modo che possa avere m
nell'ambito di topLevelFun
, in modo da poter aggiungere un vincolo e trasmettere f
. Ci deve essere un modo migliore.
Qui potrei fare una grande varietà di cose, quindi qualsiasi suggerimento sarebbe utile.
'applyFunc' promette di funzionare per qualsiasi' PrimMonad m' il _caller_ sceglie, ma poi 'runST $ do ...' forza 'm' per essere' ST s'. Puoi aggiustarlo affermando che 'g' funziona per qualsiasi' PrimMonad m' _you_ scelto, o semplicemente restringendo 'm' per essere' ST s'. Ecco il [codice] (http://hpaste.org/80991). Se questo effettivamente risponde al tuo problema, fammelo sapere e scriverò una risposta. – Vitus
Credo che funzioni, con alcune modifiche minori. Assicurati di aggiungere "Rank2Types" alle importazioni della lingua, e il tipo rank2 in "applyFunc" dovrebbe essere (per tutti i m. (PrimMonad m) => ...) Molte grazie! Rank2Types è passato alla fine. – crockeea
Ah sì, ho dimenticato "RankNTypes" in ".ghci". A proposito, credo che 'Rank2Types' sia deprecato a favore di' RankNTypes'. – Vitus