Instance error with vector when trying to generate random number - haskell

I am trying to generate random number using System.MWC package. I wrote a small test code as below:
module Main where
import Data.Word(Word32)
import Control.Monad.ST as ST
import System.Random.MWC
import Data.Vector.Generic.Base
import qualified Data.Vector.Unboxed as U
test :: Word32 -> Int
test x = runST $ do
gen <- initialize (U.fromList [x] :: U.Vector Word32)
v <- uniformR (1,100) gen
return v
The problem is I am getting instance error when trying to use initialize function. This is the instance error I get:
No instance for (vector-0.9.1:Data.Vector.Generic.Base.Vector
U.Vector Word32)
arising from a use of `initialize'
Possible fix:
add an instance declaration for
(vector-0.9.1:Data.Vector.Generic.Base.Vector U.Vector Word32)
In a stmt of a 'do' block:
gen <- initialize (U.fromList [x] :: U.Vector Word32)
In the second argument of `($)', namely
`do { gen <- initialize (U.fromList [x] :: U.Vector Word32);
v <- uniformR (1, 100) gen;
return v }'
In the expression:
runST
$ do { gen <- initialize (U.fromList [x] :: U.Vector Word32);
v <- uniformR (1, 100) gen;
return v }
Failed, modules loaded: none.
I ran info in ghci to confirm that no instances are defined for Data.Vector.Generic.Base.Vector. I then checked hackage for documentation but no page exists for that package.
So, my question is where is that missing instance defined. I can load it once I know where it is defined. Importing Data.Vector.Generic.Base.Vector doesn't work. Also, mwc-random-0.13.1.1 package has a dependency on vector-0.9.1 as you can see in the error message above.

mwc-random is picking an older installed version of vector rather than the latest one. If you uninstall the older version of vector and reinstall mwc-random to pull the updated dependency of vector-0.10, then the issue resolves itself.
(Note: See the comment chain under the question for more details)

The instances are defined one by one, individually per type.
http://code.haskell.org/vector/Data/Vector/Unboxed/Base.hs
Search for #define primVector. In particular, primVector(Word32 should be the instance you're looking for.
I don't think this fixes your problem though.

Related

Unpacking and printing values from State-Monad in Haskell using get

I am trying to get a good grasp of the State-Monad (and Monads in general) but I am struggling with rewriting the below function using the state Monad and the do-notation, which resulted as an exercise for me propose here
import Control.Monad
import System.Random
import Data.Complex
import qualified System.Random as R
import Control.Monad.Trans.State.Lazy
giveRandomElement :: [a] -> State R.StdGen a
giveRandomElement lst = do
let n = length lst
rand <- state $ randomR (0, n-1)
return $ lst !! rand
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
tal <- state $ randomR (0, 1) :: StateT StdGen Data.Functor.Identity.Identity a
if (tal == 0) then true_answer
else giveRandomElement answers
As is immediately obvious there are some type problems for the tal-variable as it occurs in the if-clause and the first line of the do-expression. As is visible from the code I have tried to force the latter by a specific type in order to make it unambiguous and clearer for myself as well. I have done so by the compiler-suggestion I got when I first tried to force it to be of the Int-type. I Am however not able to use that value in an if-statement, and I am unsure of how to convert or unpack the value such that I get it as an Int.
So far I have tried to add the folloowing line after tal <- ... , resp <- get $ tal but I get this output.
error:
* Couldn't match expected type: t0
-> StateT StdGen Data.Functor.Identity.Identity a1
with actual type: StateT s0 m0 s0
* The first argument of ($) takes one value argument,
but its type `StateT s0 m0 s0' has none
In a stmt of a 'do' block: resp <- get $ tal
In the expression:
do tal <- state $ randomR (0, 1)
resp <- get $ tal
if (resp == 0) then
giveRandomElement answers
else
giveRandomElement answers
* Relevant bindings include tal :: t0
Furthermore I am baffled what would be the best way to 'print' the result returned by giveRandomElement as the type is based on the type declared for the State-monad which as I understand it doesn't use the deriving Show also. But this can perhaps be solved by unpacking the value as enquired about above.
EDIT
I used the above packages although they are probably not all used in the above code. I am unsure of which is used by the code by I suspect the qualified System.Random as R
The following code line:
tal <- state $ randomR (0, 1) :: StateT StdGen Data.Functor.Identity.Identity a
is quite long and might cause a horizontal slider to appear, at least on my platform.
So it is all too easy to overlook that at its very end, the a type variable is used, while it should be just Int.
Also, the two branches of the if construct use different types, making the construct ill-typed. The then branch gives a pure a value, while the else branch gives a monadic value. This is easily fixed by changing to:
if (tal == 0) then return true_answer
as the (slightly misnamed) return library function wraps its argument into the monad at hand.
The following code, which tries to keep code lines short enough, seems to work fine:
import Control.Monad.State
import qualified System.Random as R
import qualified Data.Functor.Identity as DFI
giveRandomElement :: [a] -> State R.StdGen a
giveRandomElement lst = do
let n = length lst
rand <- state $ R.randomR (0, n-1)
return $ lst !! rand
type ActionType = StateT R.StdGen DFI.Identity Int
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
tal <- (state $ R.randomR (0, 1) :: ActionType)
if (tal == 0) then return true_answer
else giveRandomElement answers
main :: IO ()
main = do
let g0 = R.mkStdGen 4243
action = random_response_monad 20 [0..9]
(k, g1) = runState action g0
putStrLn $ "k is set to: " ++ (show k)
Side note: the code can also be made to compile without the complex type annotation, like this:
tal <- state $ R.randomR (0::Int, 1)
Something like this seems to work:
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
tal <- state $ randomR (0 :: Int, 1)
if (tal == 0) then return true_answer
else giveRandomElement answers
Two changes:
Use a type annotation to tell the compiler what you mean by 0 and 1. Once you've told the compiler which type 0 is, it follows that 1 has the same type. (Keep in mind that in Haskell, numbers are polymorphic. Without more information, Haskell will see a literal such as 0 as potentially any Num instance.)
return in front of true_answer.
Here's a few samples from GHCi that seems to indicate that it works:
ghci> evalState (random_response_monad 42 [0..9]) <$> newStdGen
4
ghci> evalState (random_response_monad 42 [0..9]) <$> newStdGen
1
ghci> evalState (random_response_monad 42 [0..9]) <$> newStdGen
42

Using RandomGen in newsynth

I'm new to Haskell and am trying to get some code up and running on a bit of a tight schedule, which is why I'm doing something more complicated than the absolute basics. I'm using the package newsynth and would like to use the function root_of_negative_one (documentation, source). In GHCi, I run the following commands:
Prelude> import Quantum.Synthesis.Diophantine
Prelude Quantum.Synthesis.Diophantine> :set -package random
Prelude Quantum.Synthesis.Diophantine> import System.Random
Prelude Quantum.Synthesis.Diophantine System.Random> let g = getStdGen
Prelude Quantum.Synthesis.Diophantine System.Random> let x = root_of_negative_one g 5
to try to get a square root of -1 mod 5. GHCi returns:
<interactive>:7:9: error:
• No instance for (RandomGen (IO StdGen))
arising from a use of ‘root_of_negative_one’
• In the expression: root_of_negative_one g 5
In an equation for ‘x’: x = root_of_negative_one g 5
I know that root_of_negative_one needs an input of type RandomGen but I seem to have not understood the RandomGen documentation well enough to execute this. Any help is appreciated. Thanks!
root_of_negative_one needs a StdGen, but getStdGen is an IO StdGen. You need to do g <- getStdGen instead of let g = getStdGen.

Lifting a value in the State monad in Haskell

I am writing a Sudoku generator/solver in Haskell as a learning exercise.
My solve function takes in a UArray but returns a State Int (UArray ...) so that it can also return the maximum difficulty level that it found while solving.
This is my function so far (still in the very experimental early stage):
import Control.Monad.State (State, put)
import Control.Monad.Trans.Class (lift)
import Data.Array.MArray (thaw)
import Data.Array.ST (runSTUArray)
import Data.Array.Unboxed (UArray)
-- ...
type Cell = Word16
solve :: UArray (Int, Int) Cell -> State Int (UArray (Int, Int) Cell)
solve grid = do
return $ runSTUArray $ do
arr <- thaw grid
lift $ put 42
return arr
It does not really do anything with the mutable array yet. I am simply trying to get it to type check with the put 42, but currently get the following error:
• Couldn't match kind ‘*’ with ‘* -> *’
When matching the kind of ‘ST’
• In a stmt of a 'do' block: lift $ put 42
In the second argument of ‘($)’, namely
‘do arr <- thaw grid
lift $ put 42
return arr’
In the second argument of ‘($)’, namely
‘runSTUArray
$ do arr <- thaw grid
lift $ put 42
return arr’
|
128 | lift $ put 42
| ^^^^^^^^^^^^^
runSTUArray ... is a pure value, it does not know anything about "outer monad". And State cares about how you use it, you cannot pass it opaquely into ST.
What you could do:
Option1: change the whole program to move more logic to ST side. Instead of State you'd use STRef then:
solve :: ST s (STRef Int) -> ST s (UArray (Int, Int) Cell) -> ST s ()
...
Option2: manually extract it and pass it to ST, then get back and put explicitly. But there is complication. runSTUArray does not allow getting another value together with the array. I don't know how it can be done safely with current array functions. Unsafely you could re-implement better runSTUArray which can pass another value. You could also add fake cells and encode the new state there.
The way to export another value exists in the vector package, there is (in new versions) createT function which can take not bare vector but a structure containing it (or even several vectors). So, overall, your example would be like:
import Control.Monad.State (State, put, get)
import Data.Word (Word16)
import qualified Data.Vector.Unboxed as DVU
type Cell = Word16
solve :: DVU.Vector Cell -> State Int (DVU.Vector Cell)
solve grid = do
oldState <- get
let (newState, newGrid) = DVU.createT (do
arr <- DVU.thaw grid
pure (oldState + 42, arr))
put newState
pure newGrid
vectors are one-dimensional only, unfortunately
solve grid has form return $ .... This means that State Int (UArray (Int, Int) Cell) is just specialized Monad m => m (UArray (Int, Int) Cell) - the ... does not have access to the features of this specific monad, it's just a UArray (Int, Int) Cell value that you return.
I was able to get a slight variation to compile and run after changing the State monad to a tuple (Int, Grid):
import Control.Monad.ST (ST, runST)
import Data.Array.MArray (freeze, thaw, writeArray)
import Data.Array.ST (STUArray)
import Data.Array.Unboxed (UArray)
import Data.Word (Word16)
type Cell = Word16
type Grid = UArray (Int, Int) Cell
solve :: Grid -> (Int, Grid)
solve grid =
runST $ do
mut <- thaw grid :: ST s (STUArray s (Int, Int) Cell)
writeArray mut (0, 0) 0 -- test that I can actually write
frozen <- freeze mut
return (42, frozen)
This works fine for my application.

Custom MonadState instance

When I do:
cabal sandbox init
cabal update
cabal install hakaru
cabal repl
λ> :l simple.hs
λ> sample test []
with simple.hs containing:
{-# LANGUAGE MultiParamTypeClasses #-}
import Language.Hakaru.ImportanceSampler
import Control.Monad.State
instance MonadState Int Measure
test :: Measure Int
test = put 1 >> get >>= \i -> return i
my computer runs out of memory.
How can I successfully make the Measure monad an instance of MonadState (i.e. have test above return 1)? The Measure type is already an instance of Monad with bind and return defined. Is there some default way I can define MonadState's put and get in terms of lift, bind, and return to make it work? I tried:
get = lift get
put = lift . put
but I couldn't get the (transformer?) types to work out:
simple.hs:6:9:
Couldn't match type ‘t0 m0’ with ‘Measure’
Expected type: Measure Int
Actual type: t0 m0 Int
In the expression: lift get
In an equation for ‘get’: get = lift get
simple.hs:7:9:
Couldn't match type ‘t1 m1’ with ‘Measure’
Expected type: m1 () -> Measure ()
Actual type: m1 () -> t1 m1 ()
In the first argument of ‘(.)’, namely ‘lift’
In the expression: lift . put
Measure is already defined in a following way:
newtype Measure a = Measure { unMeasure :: [Cond] -> Sampler (a, [Cond]) }
You can see that there is no place to store your Int, so you cannot make it a proper instance of MonadState.
If you want to extend Measure to MonadState, you can use StateT monad transformer:
test :: StateT Int Measure Int
test = put 1 >> get >>= \i -> return i
What happened here? StateT s is a monad transformer, which lets you to combine State s monad with any other monad (in this example Measure)
The exact code which ended up working for me is:
import Language.Hakaru.ImportanceSampler
import Language.Hakaru.Distribution
import Control.Monad.State
import System.IO.Unsafe (unsafePerformIO)
test1 :: StateT Int Measure Int
test1 = do
i <- lift $ unconditioned $ categorical [(0,0.25), (1,0.25), (2,0.5)]
j <- lift $ unconditioned $ categorical [(i,0.25), (1,0.25), (2,0.5)]
put (i + j)
k <- get
return k
run_test1 = unsafePerformIO $ empiricalMeasure 10 (evalStateT test1 0) []

"No instance for MonadRandom" when using weightedSample in a monad transformer stack

I want to take a weighted sample from a list inside a monad transformer stack.
I've managed to get this minimal example to type-check, but I don't understand the error message I get upon running main, and I don't know how to fix it.
{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts #-}
module Testing where
import Control.Monad.IO.Class (liftIO, MonadIO)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.State.Lazy (modify, runStateT, StateT)
import Control.Monad.Trans.Reader (ask, runReaderT, ReaderT)
import Data.Random
import Data.Random.Distribution.Uniform.Exclusive (Excludable)
import Data.Random.Shuffle.Weighted (weightedSample)
testS :: [(Int, Int)]
testS = [(1,c) | c <- [11..20]]
loop :: (Num w, Ord w, Show a, MonadIO m, Excludable w, Distribution Uniform w, MonadRandom (StateT [[a]] m)) => ReaderT [(w, a)] (StateT [[a]] m) ()
loop = do
s <- ask
a <- lift $ sample $ weightedSample 1 s
liftIO $ print a
lift $ modify ((:) a)
main :: (MonadIO m, MonadRandom (StateT [[Int]] m)) => m ((), [[Int]])
main = runStateT (runReaderT loop testS) []
The actual program is supposed to help with learning by selecting a random question from the initial config (testS), and then update the weights in the state so that questions the user got wrong become more likely.
Here is the error I get when running main in ghci:
No instance for (random-source-0.3.0.6:Data.Random.Internal.Source.MonadRandom
(Control.Monad.Trans.State.Lazy.StateT [[Int]] m0))
arising from a use of `main'
Possible fix:
add an instance declaration for
(random-source-0.3.0.6:Data.Random.Internal.Source.MonadRandom
(Control.Monad.Trans.State.Lazy.StateT [[Int]] m0))
In the expression: main
In an equation for `it': it = main
I can't seem to get random-fu installed to test, but based on browsing documentation I still have a guess that might be right.
The line
a <- lift $ sample $ weightedSample 1 s
Tries to run sample $ weightedSample 1 s in the underlying monad
StateT [[Int]] IO
However, StateT monads are only MonadRandoms when their state is one of the supported random number generator states.
You probably want to run it in IO, which is itself a MonadRandom.
In other words, add another lift.
BTW if this is right, the reason why it still typechecks initially is that you could in theory add an instance for StateT [[Int]] IO if you wanted. (But you probably don't.)

Resources