简体   繁体   中英

Haskell: simplifying a mutable vector type signature provided by :t

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:

  • I can drop 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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM