I made a function in haskell that is supposed to take a list along with the size of the list; and it is supposed to create a Data.Vector.Mutable.MVector with the given size, fill the vector with the contents of the list and return this vector.
TL;DR
- I want to know why the type signature I supplied didn't work. What am I missing from this that makes it unacceptable as a type signature?
- Is it possible to create a function that does what I specified above while using my type signature?
- How does one interpret the type signature generated by the compiler based on the code I wrote?
This is the function:
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
Most of it I wrote without really trying to understand what they do (the last line) and as a consequence, I am not able to come up with a suitable type signature. However, the compiler stepped in to save the day with this:
Compiler generated type signature
vecFromList
:: (PrimMonad (MVector t), PrimState (MVector t) ~ t) =>
[b] -> Int -> MVector t b
Did I hear someone say Wat? Oh that was just me, anyways... Before I tried compiling it, this is the type signature I thought should work:
The one I thought should work
vecFromList :: PrimMonad m => [t] -> Int -> MV.MVector (PrimState m) t
It should be obvious by this point that this somewhat simplistic looking type signature which seems to look exactly like what I want the function to do, does in fact not work. To come up with the type signature, I was using the type signatures of some of the other functions in the vector module that I thought were similar to it, like this one for example:
Data.Vector.Mutable.read
:: PrimMonad m => MVector (PrimState m) a -> Int -> m a
Now, I'm still relatively new to haskell so I am still trying to get used to the symbols and signs used in the language and especially come close to understanding why what appears to be simple tasks have to become such convoluted things due to Monands. For example, what is the purpose of MVector
having this kind MVector :: * -> * -> *:
??