Reputation: 21047
I can compile the following, but when I use :t qsort
I get the long, complex type signature below. However, when I add that, the program will no longer type check, without additional imports (see answer below). My best guess at defining the type is also pasted below, but doen't type check (types and monads are bewildering).
Ok, so I could add an extra import statement and it type checks, but I've never seen a code signature this complex on any code published online. So my question is:
Ord t
and exhange Int
for t
and it checks, but how do I substitute in ST
or IO
for Control.Monad.Primitive.PrimMonad
, and what do I do with v
.I'm trying to write a blog post that provides an example of how to use these various Monads, and by contrast for Arrays the type signature of qsort is a more manageable qsort :: (STArray s Int Int) -> Int -> Int -> ST s ()
. (For those that want to understand s
there are lots of explanations on line, all of which passed slightly above my head - I get that it is a clever trick to get the type checker itself to prevent the author writing code where data from the Monad leaks out and thus leads to impurity.)
import Control.Monad
import Control.Monad.ST
import qualified Data.Vector as V
import qualified Data.Vector.Generic.Mutable as MV
main = do
lines <- BS.lines `fmap` BS.readFile "10.txt"
let
inputData = Prelude.map (maybe (error "can't read Int") fst . BS.readInt) lines
initialImmutableVector = V.fromList inputData
print $ runST $ do
state <- V.thaw initialImmutableVector
qsort state 0 (Prelude.length inputData - 1)
frozen <- V.freeze state
return frozen
--qsort :: (MV.MVector s Int) -> Int -> Int -> ST s ()
--qsort
-- :: (Ord t, Control.Monad.Primitive.PrimMonad m, MV.MVector v t) =>
-- v (Control.Monad.Primitive.PrimState m) t -> Int -> Int -> m ()
qsort vec min mx =
if mx - min < 1 then
return ()
else do
p <- MV.read vec min
final_i <- foldM (partitioner p) (min+1) [(min+1)..mx]
swap min (final_i - 1)
qsort vec min (final_i-2)
qsort vec final_i mx
where
swap i j = do
vec_i <- MV.read vec i
vec_j <- MV.read vec j
MV.write vec i vec_j
MV.write vec j vec_i
partitioner p i acc = do
vec_acc <- MV.read vec acc
if vec_acc > p then
return i
else do
swap i acc
return $ i+1
Upvotes: 1
Views: 363
Reputation: 2005
Importing function(-s) does not import their types. If your code explicitly refers to the type, it has to be imported. You can use imported functions without importing the types of their arguments or return values as long as the code does not explicitly refer to those types. Once you start using types or classes explicitly, you have to import them, this is intentional.
Upvotes: 4
Reputation: 2069
It looks like your last attempt is correct, but perhaps you didn't import everything you needed? The code you pasted as-is doesn't compile with or without type signatures. Here's a very slightly modified version of what you have that works just fine for me (with GHC 7.8.3):
import Control.Monad
import Control.Monad.ST
import qualified Data.Vector as V
import qualified Data.Vector.Generic.Mutable as MV
import qualified Data.ByteString.Char8 as BS
import Control.Monad.Primitive (PrimState, PrimMonad)
import Prelude hiding (lines, min)
main :: IO ()
main = do
lines <- BS.lines `fmap` BS.readFile "10.txt"
let
inputData = map (maybe (error "can't read Int") fst . BS.readInt) lines
initialImmutableVector = V.fromList inputData
print $ runST $ do
state <- V.thaw initialImmutableVector
qsort state 0 (Prelude.length inputData - 1)
frozen <- V.freeze state
return frozen
qsort :: (Ord t, PrimMonad m, MV.MVector v t)
=> v (PrimState m) t -> Int -> Int -> m ()
qsort vec min mx =
if mx - min < 1 then
return ()
else do
p <- MV.read vec min
final_i <- foldM (partitioner p) (min+1) [(min+1)..mx]
swap min (final_i - 1)
qsort vec min (final_i-2)
qsort vec final_i mx
where
swap i j = do
vec_i <- MV.read vec i
vec_j <- MV.read vec j
MV.write vec i vec_j
MV.write vec j vec_i
partitioner p i acc = do
vec_acc <- MV.read vec acc
if vec_acc > p then
return i
else do
swap i acc
return $ i+1
Upvotes: 1