implicitly coerce types in a Haskell do block?

My question relates to the answer to another question: https://stackoverflow.com/a/11766789/3212958

In his answer, ertes writes the following type signature

select :: [a] -> [(a, [a])]

However, when select is actually used, ertes writes the following inside of a do block

(y, ys) <- select xs

Please help me shed some light on how the tuple (y, ys) matches the return type of select, namely [(a, [a])] . Is Haskell coercing the types at some point? (Does Haskell ever coerce types?) Is <- extracting a tuple of type (a, [a]) from the list monad that select returns?

Thanks, Max

--- EDIT: ---

@Lee reminds newbs to desugar before trying to reason about types. After making >>= explicit, it's more clear what's going on. After desugaring, the function in question looks like:

select xs >>= (y, ys) -> fmap (y:) (perms (n - 1) ys)

And for lists, xs >>= f = concat (map f xs) . So a better reading of (y, ys) in this context is as the signature of the function to map over the list.


In do notation,

do x1 <- action1
   action2

is translated into action1 >>= x1 -> action2

This means that if action1 has type ma for some monad m , then x1 has type a . It's not really coercing types, but rather 'unpacking' the value from the monadic action action1 and binding it to x1 .


(y, ys) is of type (b, c)

The return type of select is of type [(a, [a])]

In <- the types are actually d and Monad m => md . So we can write the following type equalities:

(b, c) ~ d
[(a, [a])] ~ Monad m => m d

Solving is easy. First substitute d from first equation into second equation:

[(a, [a])] ~ Monad m => m (b, c)

Now to see what's going on I will use a prefix form of [] type constructor (it's not valid haskell but you should get the idea):

[] (a, [a]) ~ Monad m => m ( b, c)

So

m ~ []
(a, [a]) ~ (b, c)

At this point the compiler checks that instance Monad [a] exists. The rest is easy:

a ~ b
[a] ~ c
链接地址: http://www.djcxy.com/p/43036.html

上一篇: 类型签名过于笼统; 缺少约束?

下一篇: 在Haskell do块中隐式强制类型?