LordofTurtles
LordofTurtles

Reputation: 65

Type error for an unbound variable?

I have the following section of code:

run :: State' s a -> s -> (a, Counts)
run s x = do
        put x
        p <- runState' s
        (1, Counts 0 0 0 0)

When I try to compile this, I get the error couldn't match expected type (a, t0) with actual type (s,counts) -> (a,s,counts)
However, p's type shouldn't be constrained by anything should it?

The following is the code describing the State' datatype, in case it is needed

newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }

instance Functor (State' s) where
    fmap = liftM

instance Applicative (State' s) where
    pure  = return
    (<*>) = ap

instance Monad (State' s) where

    -- return :: a -> State' s a
    return x = State' f
                where f = \(s, count) -> (x,s,count <> oneReturn)

    -- (>>=) :: State' s a -> (a -> State' s b) -> State' s b
    st >>= k = State' (\(s, count) -> let (x,s',count') = runState' st (s, count) in runState' (k x) (s',count' <> oneBind))

instance MonadState (State' s) s where

    -- get :: State' s s
    get = State' (\(s, count) -> (s, s, count <> oneGet))

    -- put :: s -> State' s ()
    put s' = State' (\(s, count) -> ((), s', count <> onePut))

Side note, I am also stumped as to how I would get the "count" part of the state' out of the state' so I can write it on the screen

Maybe it's more helpful to explain what run is supposed to do.
For instance if you use a function label, that labels each node in a tree with an incrementing number using a state, and then execute run (label tree) 30 It is supposed to put 30 in the state, run label (so it starts at 30 with labeling) then print the resulting tree on the screen, as well as the "count"portion of the state, which tracks how often monadic operations and get/put are done on it

Upvotes: 0

Views: 791

Answers (1)

Christian Conkle
Christian Conkle

Reputation: 5992

The fundamental problem here is that you're using do notation inappropriately. Any block of do code must have a monadic type, such as:

example :: String -> IO ()
example s = do { ... }

The type IO is a Monad. Your do block has type (a, Counts). This is not a monadic type.

I think what you want is this:

run :: State' s a -> s -> (a, Counts)
run s x = (a, c)
  where (a, _, c) = runState' s x

But you wrote something so different from that that I'm not confident I understand where you're going with it. Leave a comment if this doesn't make sense.

Upvotes: 1

Related Questions