Reputation: 34081
I have following type:
newtype Moi s a =
Moi { runMoi :: s -> (a, s) }
the data constructor expects a function as the argument and it should return a tuple.
I tried following:
*OwnState> :t Moi (+1)
the compiler complains:
<interactive>:1:6: error:
* Occurs check: cannot construct the infinite type: s ~ (a, s)
Expected type: s -> (a, s)
Actual type: (a, s) -> (a, s)
* In the first argument of `Moi', namely `(+ 1)'
In the expression: Moi (+ 1)
First look at the type signature of (+1)
:
*OwnState> :t (+1)
(+1) :: Num a => a -> a
The type a
has to be constraint to Num
typeclass.
So when I write Moi (+1)
, what is going to happen, how the type is going to be substitute?
Let's analyze the error message as the next step:
Occurs check: cannot construct the infinite type: s ~ (a, s)
Tilde means ~
type equality and how the compiler comes to conclusion that s
has the same type as (a, s)
?
I suppose, the type substitution of example above works in this way:
n -> n "Type of (+1)
| |
s -> (a, s)
then s
becomes to (a, s)
and the proof s ~ (a, s)
is true.
(a, s) -> (a, s)
But I can not see, why it is infinite type.
Upvotes: 3
Views: 76
Reputation: 476659
But I can not see, why it is infinite type.
Because s
occurs both at the left and right side of the type equality ~
, and this in a recursive fashion. After one substitution, we have:
s ~ (a,s)
But note that s
in (a,s)
should also be substituted, so:
s ~ (a,s) ~ (a,(a,s)) ~ (a,(a,(a,s))) ~ ...
So in order to construct this type it would result in a type with infinitely nested 2-tuples. Haskell can not handle such types.
Moi (+1)
simply does not match the specifications of this "state monad". You probably want to use:
Moi (\x -> (x,x+1))
or:
Moi (ap (,) (1 +))
Upvotes: 7