Help with Why Do Monads Matter blog post understanding

Hi, I've been reading the following blog post https://cdsmith.wordpress.com/2012/04/18/why-do-monads-matter/ And I think I like it. But there's a part that I don't get. "For a set A, we will define the set Pref(A) to be the set of functions from application settings to the set A. Now watch closely: a function in context from A to B is just an ordinary function from A to Pref(B). In other words, you give it a value from the set A, and it gives you back another function that maps from application settings to the set B." This is in the "functioning with dependency" section and is talking about a procedure that uses outside info from preferences or application settings. If I set my prefs as follows configvar = 3 and define a function as follows add x = configvar + 6 So add’s signature is add: int -> int What does prefs(int) look like? Is that even the right thing to ask? What happens to the add function? By substituting the B for Prefs(B) and returning now only functions from Pref(B) don't we lose the rest of the mapping for add i.e., " + 6"? Matt.

On Fri, Jun 29, 2012 at 09:57:42AM +0100, Matt Ford wrote:
Hi,
I've been reading the following blog post
https://cdsmith.wordpress.com/2012/04/18/why-do-monads-matter/
And I think I like it. But there's a part that I don't get.
"For a set A, we will define the set Pref(A) to be the set of functions from application settings to the set A. Now watch closely: a function in context from A to B is just an ordinary function from A to Pref(B). In other words, you give it a value from the set A, and it gives you back another function that maps from application settings to the set B."
This is in the "functioning with dependency" section and is talking about a procedure that uses outside info from preferences or application settings.
If I set my prefs as follows
configvar = 3
and define a function as follows
add x = configvar + 6
So add’s signature is
add: int -> int
What does prefs(int) look like? Is that even the right thing to ask?
prefs(int) looks like Config -> Int (in your example perhaps we define type Config = Int), so add should have type Int -> (Config -> Int) The thing that is confusing the issue here is that you just made add implicitly use the 'configvar' which is in scope, so it does not need to take it as a parameter. But imagine that you want to be able to do multiple runs with different configurations, without recompiling your program -- then you will need to have any function that needs the configuation take it as an input. Like this: add x config = config + 6
By substituting the B for Prefs(B) and returning now only functions from Pref(B) don't we lose the rest of the mapping for add i.e., " + 6"?
I don't think I understand this question. -Brent

On 29 June 2012 19:52, Brent Yorgey
"For a set A, we will define the set Pref(A) to be the set of functions from application settings to the set A. Now watch closely: a function in context from A to B is just an ordinary function from A to Pref(B). In other words, you give it a value from the set A, and it gives you back another function that maps from application settings to the set B."
This is in the "functioning with dependency" section and is talking about a procedure that uses outside info from preferences or application settings.
If I set my prefs as follows
configvar = 3
and define a function as follows
add x = configvar + 6
So add’s signature is
add: int -> int
What does prefs(int) look like? Is that even the right thing to ask?
prefs(int) looks like Config -> Int (in your example perhaps we define type Config = Int), so add should have type
Int -> (Config -> Int)
The thing that is confusing the issue here is that you just made add implicitly use the 'configvar' which is in scope, so it does not need to take it as a parameter.
That's what I'm trying to understand, how we switch from "impure" functions to "pure" functions which don't rely on external state. And I see that passing in functions that act on the state helps do this. But I don't understand how, for a function that looks like A->B, that has a whole load dependencies on external variables and functions (of perhaps lot's of different types) all these variables and functions are captured by the definition of Pref(B). And by changing the actual type of the result of A->B in this case from an Int to a function that returns an Int how can this hope to match the original intention of the impure A->B. Say for example Pref(b) is the empty set as no functions map to from the config to B. Changing the range means we will never get a sensible result?? I feel as though I'm missing something. Cheers.
But imagine that you want to be able to do multiple runs with different configurations, without recompiling your program -- then you will need to have any function that needs the configuation take it as an input. Like this:
add x config = config + 6
By substituting the B for Prefs(B) and returning now only functions from Pref(B) don't we lose the rest of the mapping for add i.e., " + 6"?
I don't think I understand this question.
-Brent
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On 29 June 2012 21:30, Matt Ford
On 29 June 2012 19:52, Brent Yorgey
wrote: And I see that passing in functions that act on the state helps do this. But I don't understand how, for a function that looks like A->B, that has a whole load dependencies on external variables and functions (of perhaps lot's of different types) all these variables and functions are captured by the definition of Pref(B).
And by changing the actual type of the result of A->B in this case from an Int to a function that returns an Int how can this hope to match the original intention of the impure A->B. Say for example Pref(b) is the empty set as no functions map to from the config to B. Changing the range means we will never get a sensible result??
I feel as though I'm missing something.
That paragraph introduces the notion of currying. Fast forward - the objective is to test the returning function. Usually, with "maybe" result or "just" result. This is a way to isolate (the understanding of) what the code does from (side) effects that are not expected. Effects do happen. The idea is to restrict their "area of effect" inside a monad, so the code just does what we expect (machines are funny like that) and nothing else. "Abstraction Over Monads" introduces the advantage of having this abstraction in Haskell "by design". [quote] sequence :: Monad m => [m a] -> m [a] (...) It’s basically a convenient way to check a whole list of computations for a failure. [/quote]

On Fri, Jun 29, 2012 at 09:30:58PM +0100, Matt Ford wrote:
On 29 June 2012 19:52, Brent Yorgey
wrote: "For a set A, we will define the set Pref(A) to be the set of functions from application settings to the set A. Now watch closely: a function in context from A to B is just an ordinary function from A to Pref(B). In other words, you give it a value from the set A, and it gives you back another function that maps from application settings to the set B."
This is in the "functioning with dependency" section and is talking about a procedure that uses outside info from preferences or application settings.
If I set my prefs as follows
configvar = 3
and define a function as follows
add x = configvar + 6
So add’s signature is
add: int -> int
What does prefs(int) look like? Is that even the right thing to ask?
prefs(int) looks like Config -> Int (in your example perhaps we define type Config = Int), so add should have type
Int -> (Config -> Int)
The thing that is confusing the issue here is that you just made add implicitly use the 'configvar' which is in scope, so it does not need to take it as a parameter.
That's what I'm trying to understand, how we switch from "impure" functions to "pure" functions which don't rely on external state.
And I see that passing in functions that act on the state helps do this. But I don't understand how, for a function that looks like A->B, that has a whole load dependencies on external variables and functions (of perhaps lot's of different types) all these variables and functions are captured by the definition of Pref(B).
Well, in that case Pref would have to be some sort of record of all the possible things it could depend on. Note that Pref(A) does *not* mean "the set of functions from *whatever application settings A happens to use* to A". That would not be very useful (and impossible to implement). Rather, one must fix ahead of time what counts as "application settings". Then everything involving Pref will have access to that fixed set of application settings. Does that help at all?
And by changing the actual type of the result of A->B in this case from an Int to a function that returns an Int how can this hope to match the original intention of the impure A->B. Say for example Pref(b) is the empty set as no functions map to from the config to B. Changing the range means we will never get a sensible result??
I don't think I understand this. Can you give an example? There is definitely something fundamental you are misunderstanding but I am not quite sure what it is. Does my clarification above help at all? -Brent
participants (3)
-
Brent Yorgey
-
Matt Ford
-
Paulo Pocinho