Yes, it is indeed impossible. Consider the following definition of State:
newtype State s a = State { runState :: s -> (a, s) }
To extract the value this data type we would first need to supply some state.
We can create a specialized extract function if we know the type of the state. For example:
extract' :: State () a -> a
extract' (State f) = f ()
extractT :: State Bool a -> a
extractT (State f) = f True
extractF :: State Bool a -> a
extractF (State f) = f False
However, we can't create a generic extract function. For example:
extract :: State s a -> a
extract (State f) = f undefined
The above extract function is generic. The only state we can supply is ⊥ which is incorrect. It is only safe if the function f :: s -> (a, s) passes along its input transparently (i.e. f = (,) a for some value a). However, f may take some state and use it to generate some value and a new state. Hence, f may use its input non-transparently and if the input is ⊥ then we get an error.
Thus, we cannot create a generic extract function for the State data type.
Now, for a data type to be an instance of Traversable it first needs to be an instance of Foldable. Hence, to make State an instance of Traversable we first need to define the following instance:
instance Foldable (State s) where
foldMap f (State g) = mempty
-- or
foldMap f (State g) = let x = f (extract g) in mconcat [x]
-- or
foldMap f (State g) = let x = f (extract g) in mconcat [x,x]
-- or
foldMap f (State g) = let x = f (extract g) in mconcat [x,x,x]
-- ad infinitum
Note that foldMap has the type Monoid m => (a -> m) -> State s a -> m. Hence, the expression foldMap f (State g) must return a value of the type Monoid m => m. Trivially, we can always return mempty by defining foldMap = const (const mempty). However, in my humble opinion this is incorrect because:
- We aren't really folding anything by always returning
mempty.
- Every data type can be trivially made an instance of
Foldable by always returning mempty.
The only other way to produce a value of the type Monoid m => m is to apply f to some value x of the type a. However, we don't have any value of the type a. If we could extract the value a from State s a then we could apply f to that value, but we already proved that it's not possibly to define a generic extract function for State s a that never crashes.
Thus, State s cannot be made an instance of Foldable and consequently it cannot be an instance of Traversable.