understanding function signature alignement

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

understanding function signature alignement

simkestuff@gmail.com
Hello,

I'm going through Haskellbook and while doing some exercises I'm stack with trying to explain myself how types matches in this examples:

meh :: Monad m => [a] -> (a -> m b) -> m [b]
meh [] _      = pure []
meh (x:xs) f = (:) <$> f x <*> meh xs f


flipType :: (Monad m) => [m a] -> m [a]
flipType xs = meh xs id

What puzzles me is how id function which is of type (a->a) can fit here where meh function is requesting function of type (a->m b)?

The function (a -> m b) is function that says give me anything and I will give back anything wrapped up into some monad structure; id ( a -> a) on other hand says give me anything and I will return it back to you. So, to me, the first function is somehow more restricted than id function because it puts limitation on what output of that function can be and I'm struggling to understand how id function can fit here.

I hope someone can help me how to reason about these functions here?

thanks



_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: understanding function signature alignement

Tony Morris-4

The (a) and (b) are different in each case. Let's rewrite it and rename the variables to emphasise the difference.

meh :: Monad m => [a] -> (a -> m b) -> m [b]

flipType :: (Monad k) => [k x] -> k [x]

id :: q -> q

This means that id can accept any argument type, as long as it returns the same argument type. For example:

id :: m b -> m b

When it is used like that, then (a) turns into (m b).

Similarly, meh can have this type:

meh :: Monad m => [m b] -> (m b -> m b) -> m [b]

All I did was specialise the (a) type-variable, which can be anything, as long as they all change. Now it is clear that when I put id into the second argument position, I get the type [m b] -> m [b]


On 09/08/18 18:32, [hidden email] wrote:
Hello,

I'm going through Haskellbook and while doing some exercises I'm stack with trying to explain myself how types matches in this examples:

meh :: Monad m => [a] -> (a -> m b) -> m [b]
meh [] _      = pure []
meh (x:xs) f = (:) <$> f x <*> meh xs f


flipType :: (Monad m) => [m a] -> m [a]
flipType xs = meh xs id

What puzzles me is how id function which is of type (a->a) can fit here where meh function is requesting function of type (a->m b)?

The function (a -> m b) is function that says give me anything and I will give back anything wrapped up into some monad structure; id ( a -> a) on other hand says give me anything and I will return it back to you. So, to me, the first function is somehow more restricted than id function because it puts limitation on what output of that function can be and I'm struggling to understand how id function can fit here.

I hope someone can help me how to reason about these functions here?

thanks




_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: understanding function signature alignement

sasa bogicevic
You can also put another function as the argument to the id :

ghci > x :: a -> m b;x = undefined
ghci > :t (id x)
(id x) :: a -> m b

On 9 Aug 2018, at 10:36, Tony Morris <[hidden email]> wrote:

The (a) and (b) are different in each case. Let's rewrite it and rename the variables to emphasise the difference.

meh :: Monad m => [a] -> (a -> m b) -> m [b]

flipType :: (Monad k) => [k x] -> k [x]

id :: q -> q

This means that id can accept any argument type, as long as it returns the same argument type. For example:

id :: m b -> m b

When it is used like that, then (a) turns into (m b).

Similarly, meh can have this type:

meh :: Monad m => [m b] -> (m b -> m b) -> m [b]

All I did was specialise the (a) type-variable, which can be anything, as long as they all change. Now it is clear that when I put id into the second argument position, I get the type [m b] -> m [b]


On 09/08/18 18:32, [hidden email] wrote:
Hello,

I'm going through Haskellbook and while doing some exercises I'm stack with trying to explain myself how types matches in this examples:

meh :: Monad m => [a] -> (a -> m b) -> m [b]
meh [] _      = pure []
meh (x:xs) f = (:) <$> f x <*> meh xs f


flipType :: (Monad m) => [m a] -> m [a]
flipType xs = meh xs id

What puzzles me is how id function which is of type (a->a) can fit here where meh function is requesting function of type (a->m b)?

The function (a -> m b) is function that says give me anything and I will give back anything wrapped up into some monad structure; id ( a -> a) on other hand says give me anything and I will return it back to you. So, to me, the first function is somehow more restricted than id function because it puts limitation on what output of that function can be and I'm struggling to understand how id function can fit here.

I hope someone can help me how to reason about these functions here?

thanks




_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: understanding function signature alignement

simkestuff@gmail.com
In reply to this post by simkestuff@gmail.com
Thanks, it is still a bit fuzzy to me ...

I understand what you did  but what confuses me is that when i look at function with signature like 

f :: Monad m => c -> m d

I always think that return type is somehow restricted in comparison to input because it demands that output type is wraped inside something (monad in this case).

For such signature to fit id signature (a -> a) ,  c type shoud be also wraped inside monad but it is not case here... 

Anyhow, I still have to figure it out

thanks 

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: understanding function signature alignement

Theodore Lief Gannon
You're right that the return type is more restricted than the argument, but it's in an *absolute* sense, not a relative one. It's not possible to relax `m d` to make it the same type as `c`, but it IS possible to constrain `c` to be the same as `m d`! And that's how `id` works here: the input in this case is known to be the same type as the output. You need something wrapped in a monad, and you already have that, so you just use it as-is.

On Thu, Aug 9, 2018, 7:22 AM [hidden email] <[hidden email]> wrote:
Thanks, it is still a bit fuzzy to me ...

I understand what you did  but what confuses me is that when i look at function with signature like 

f :: Monad m => c -> m d

I always think that return type is somehow restricted in comparison to input because it demands that output type is wraped inside something (monad in this case).

For such signature to fit id signature (a -> a) ,  c type shoud be also wraped inside monad but it is not case here... 

Anyhow, I still have to figure it out

thanks 
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: understanding function signature alignement

simkestuff@gmail.com
Yes, thinking it the terms that something which is absolutely free to be whatever, can be restricted and reduced into something else while other way around is not possible is usefull;
thanks

On Fri, Aug 10, 2018 at 12:06 PM Theodore Lief Gannon <[hidden email]> wrote:
You're right that the return type is more restricted than the argument, but it's in an *absolute* sense, not a relative one. It's not possible to relax `m d` to make it the same type as `c`, but it IS possible to constrain `c` to be the same as `m d`! And that's how `id` works here: the input in this case is known to be the same type as the output. You need something wrapped in a monad, and you already have that, so you just use it as-is.

On Thu, Aug 9, 2018, 7:22 AM [hidden email] <[hidden email]> wrote:
Thanks, it is still a bit fuzzy to me ...

I understand what you did  but what confuses me is that when i look at function with signature like 

f :: Monad m => c -> m d

I always think that return type is somehow restricted in comparison to input because it demands that output type is wraped inside something (monad in this case).

For such signature to fit id signature (a -> a) ,  c type shoud be also wraped inside monad but it is not case here... 

Anyhow, I still have to figure it out

thanks 
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners