Yes, this is really impossible. Consider the following definition of State :
newtype State sa = State { runState :: s -> (a, s) }
In extract value of this data type would initially provide some state.
We can create a specialized extract function if we know the type of 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 cannot create a general extraction function. For example:
extract :: State sa -> a extract (State f) = f undefined
The above extract function is common. The only condition we can set is & bottom; which is wrong. This is safe if the function f :: s -> (a, s) transparently passes through its input signal (i.e. f = (,) a for some value of a ). However, f can take a certain state and use it to generate some value and a new state. Therefore, f can use its input opaque, and if the input is & bottom; then we get an error.
Thus, we cannot create a general extract function for the State data type.
Now, for a data type to be an instance of Traversable , it must first be an instance of Foldable . Therefore, to make the State instance of Traversable , we must first 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 is of type Monoid m => (a -> m) -> State sa -> m . Therefore, the expression foldMap f (State g) should return a value of type Monoid m => m . Trivially, we can always return mempty by defining foldMap = const (const mempty) . However, in my humble opinion, this is not true because:
- In fact, we do not collapse anything, always return
mempty . - Each data type can be trivially created by a
Foldable instance, always returning mempty .
The only way to create a value of type Monoid m => m is to apply f to some value x type a . However, we have no value of type a . If we could extract value of a from State sa , then we could apply f to this value, but we have already proved that it cannot determine the general extract function State sa , which will never work.
Thus, State s cannot be made an instance of Foldable and, therefore, it cannot be an instance of Traversable .