2015-05-05 127 views
3

我在haskell中做了一個函數,該函數應該隨列表的大小一起列出一個列表;它應該創建一個具有給定大小的Data.Vector.Mutable.MVector,向列表中的內容填充該向量並返回該向量。Haskell類型簽名和Monads

TL; DR

  • 我想知道爲什麼我提供的類型簽名沒有工作。我錯過了什麼,使它作爲一個類型簽名是不可接受的?
  • 是否有可能創建一個函數來完成我在使用我的類型簽名時指定的內容?
  • 如何根據我編寫的代碼解釋編譯器生成的類型簽名?

這是函數:

vecFromList lst sz = MV.new sz >>= (\vec -> fillV (zip [0..sz - 1] lst) vec) where 
    fillV [] vec = vec 
    fillV ((i, v):xs) vec = MV.write vec i v >> fillV xs vec 

它的大部分我沒有真正試圖瞭解他們在做什麼(最後一行),並因此寫了,我不能拿出帶有適當的類型簽名。但是,編譯臨危受命,拯救世界這個:

編譯器生成的類型簽名

vecFromList 
    :: (PrimMonad (MVector t), PrimState (MVector t) ~ t) => 
    [b] -> Int -> MVector t b 

難道我聽到有人說笏?哦,那只是我,反正... 之前,我試圖編譯它,這是我認爲的類型簽名應該工作:

我認爲一個人應該工作

vecFromList :: PrimMonad m => [t] -> Int -> MV.MVector (PrimState m) t 

它應該是通過這一點很明顯,這看起來有些簡單化的看起來類型的簽名看起來完全像我想要的功能,事實上不是工作。要拿出類型簽名,我用的一些載體模塊中的其他功能類型簽名,我認爲是相似的,就像這樣一個例子:

Data.Vector.Mutable.read 
    :: PrimMonad m => MVector (PrimState m) a -> Int -> m a 

現在,我對於haskell來說還是比較新的,所以我仍然試圖習慣語言中使用的符號和符號,尤其是接近理解爲什麼看起來很簡單的任務由於Monands而變得如此複雜。例如,具有這種類型的MVector的目的是什麼MVector :: * -> * -> *: ??

回答

5

你快到了。你預期的類型簽名是正確的,除了造成MVector需要在單子m

vecFromList :: PrimMonad m => [t] -> Int -> m (MV.MVector (PrimState m) t) 

fillV函數的類型應該是

fillV :: [(Int, t)] 
      -> MV.MVector (PrimState m) t -> m (MV.MVector (PrimState m) t) 

但你[]情況下給出了無載體return將其轉換爲m類型。這裏有一個工作版本:

vecFromList :: PrimMonad m => [t] -> Int -> m (MV.MVector (PrimState m) t) 
vecFromList lst sz = MV.new sz >>= (\vec -> fillV (zip [0..sz - 1] lst) vec) where 
    fillV [] vec   = return vec 
    fillV ((i, v):xs) vec = MV.write vec i v >> fillV xs vec 

和工作示例:

> V.create $ vecFromList [1,2,3] 3 
fromList [1,2,3] 

注意,你實際上並不在你的fillV功能,你只能參考它修改vec,你可以使用從for_功能Data.Foldable而不是顯式編寫一個循環。我常寫可變矢量代碼do塊,因爲它使事情更清晰的對我來說:

vecFromList2 :: PrimMonad m => [t] -> Int -> m (MV.MVector (PrimState m) t) 
vecFromList2 l n = do 
    v <- MV.new n 
    for_ (zip [0..n - 1] l) $ \(i,a) -> MV.write v i a 
    return v 

與哈斯克爾可變矢量不幸的是工作可能很麻煩,它需要實踐。使用TypedHolesPartialTypeSignatures可以提供幫助。

原因MVectorPrimState m它,所以它可以使用STIO。你可以找到它的解釋here

+0

你是不是要寫'forM_'而不是'for_'?謝謝 – smac89

+0

@ Smac89 ['for_'](https://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Foldable.html#v:for_)和['forM_'](https:/ /hackage.haskell.org/package/base-4.8.0.0/docs/Data-Foldable.html#v:forM_)基本上是一樣的,'for_'只是有一個較弱的('Applicative')約束。 – cchalmers