Haskell:简化由t提供的可变向量类型签名:

时间:2014-10-26 18:28:47

标签: haskell

我可以编译以下内容,但是当我使用:t qsort时,我会在下面获得长而复杂的类型签名。但是,当我添加它时,程序将不再进行类型检查,无需额外导入(请参阅下面的答案)。我对定义类型的最佳猜测也粘贴在下面,但不要键入check(类型和monad是令人困惑的)。

好的,所以我可以添加一个额外的import语句并进行类型检查,但我从来没有在网上发布的任何代码上看到这个复杂的代码签名。所以我的问题是:

  • 我可以删除Ord t并为Int拨出t并进行检查,但如何在STIO中替换为Control.Monad.Primitive.PrimMonad },我该如何处理v

我正在尝试编写一个blog post,它提供了如何使用这些Monad的示例,而对于Arrays,qsort的类型签名是一个更易于管理的qsort :: (STArray s Int Int) -> Int -> Int -> ST s ()。 (对于那些想要理解s的人来说,有很多解释在线,所有这些都在我头脑中稍微过去了 - 我知道这是一个聪明的技巧,可以让类型检查器本身阻止作者编写代码来自Monad的数据泄漏,从而导致杂质。)

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

2 个答案:

答案 0 :(得分:4)

导入功能(-s)不会导入其类型。如果您的代码明确引用了类型,则必须导入它。只要代码未明确引用这些类型,您就可以使用导入的函数而无需导入其参数类型或返回值。一旦明确开始使用类型或类,就必须导入它们,这是故意的。

答案 1 :(得分:1)

看起来你的最后一次尝试是正确的,但也许你并没有导入你需要的一切?您粘贴的代码不会使用或不使用类型签名进行编译。这里有一个非常轻微修改过的版本,对我来说效果很好(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