Send Beginners mailing list submissions to
        beginners@haskell.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        beginners-requ...@haskell.org

You can reach the person managing the list at
        beginners-ow...@haskell.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1.  Re: let indenting problems (Heinrich Apfelmus)
   2.  Re: Finite State Machine .. (Heinrich Apfelmus)
   3. Re:  Re: clarification on IO (Gregg Reynolds)
   4.  Re: clarification on IO (Will Ness)
   5.  Re: clarification on IO (Will Ness)


----------------------------------------------------------------------

Message: 1
Date: Mon, 02 Mar 2009 12:06:31 +0100
From: Heinrich Apfelmus <apfel...@quantentunnel.de>
Subject: [Haskell-beginners] Re: let indenting problems
To: beginners@haskell.org
Message-ID: <gogehq$i0...@ger.gmane.org>
Content-Type: text/plain; charset=ISO-8859-1

7stud wrote:
>
> import Data.List (sortBy)
> 
> mySort xs = sortBy myCompare xs
>     where myCompare x y  
>               | lx < ly    = LT
>               | lx == ly   = EQ
>               | lx > ly    = GT            
>              where lx = length x
>                    ly = length y

How about

   import Data.Ord (comparing)

   mySort = sortBy (comparing length)

or at least

   mySort = sortBy myCompare
       where
       myCompare x y = compare (length x) (length y)


Regards,
apfelmus

--
http://apfelmus.nfshost.com



------------------------------

Message: 2
Date: Mon, 02 Mar 2009 12:10:12 +0100
From: Heinrich Apfelmus <apfel...@quantentunnel.de>
Subject: [Haskell-beginners] Re: Finite State Machine ..
To: beginners@haskell.org
Message-ID: <gogeom$ip...@ger.gmane.org>
Content-Type: text/plain; charset=ISO-8859-1

Tom Poliquin wrote:
> Heinrich Apfelmus wrote:
>>
>> You probably want guards, like this
>> 
>>  fib n
>>     | n == 0    = 0
>>     | n == 1    = 1
>>     | otherwise = fib (n-1) + fib (n-2)
> 
> Is this what you had in mind?
> 
> module Main where
> 
> foo a b c
>      | p1 && p2 || not p3 = 42
>      | p1 || not p2 && p3 = 13
>      | otherwise = 0
>   where
>    -- setup if predicates
>        p1 = a > b
>        p2 = a + b > 2
>        p3 = a - b < 1
> 
> main = do
>         x <- return $ foo 9 2 3
>         print x
> 
> --   42

Yes.

Of course, it will become clunky very quickly; only abstraction and
insights into the problem domain can help in these cases.


Regards,
apfelmus

--
http://apfelmus.nfshost.com



------------------------------

Message: 3
Date: Mon, 2 Mar 2009 06:48:34 -0600
From: Gregg Reynolds <d...@mobileink.com>
Subject: Re: [Haskell-beginners] Re: clarification on IO
To: Will Ness <will_...@yahoo.com>
Cc: beginners@haskell.org
Message-ID:
        <75cc17ac0903020448m4f98343dg663df3450c400...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

On Sun, Mar 1, 2009 at 11:59 AM, Will Ness <will_...@yahoo.com> wrote:


> The IO-action is not the I/O operation in the real world, but an action of
> recording a promise to perform it.
>
> Any IO primitive can be seen as latching this hidden promise onto its
> explicit
> return value, thus creating a monadic value (:: IO a), carrying along this
> hidden promise. IO bind combines these promises into a combined record, or
> log,
> of promises to perform actual I/O activity, if called upon by the system.
>
> That recording of a promise is the IO-action that IO monad is about, from
> pure
> Haskell standpoint.
>

Ok, I kinda like the idea of accumulating a "log" of promised actions,
although I'd suggest a different term since log usually means history.
Maybe antilog or prelog or future trace or the like.  In any case, I think
that's useful for explaining lazy evaluation, but it's not directly
implicated by monad semantics.  IOW monad semantics and evaluation strategy
are (mostly) orthogonal.


> Another monad will have another meaning for its actions, latching another
> hidden data on their results, but they still can be seen as actions, in
> context
> of being sequenced and combined by that monad's bind.
>

I see, you're thinking of action as something like the promised eval.  As
opposed to the action of performing actual IO.  I fear that might confuse
newcomers, though; probably better to stick with "function" terminology and
discuss evaluation separately.

>
> > Correction:  special name for IO "functions" (actually "IO terms" would
> be
> better).
>
>
> Why? They are just fuctions, of type (Monad m => a -> m b). What I'm
> saying,
> they are of special type, chainable by the M monad, so it seems logical to
> have
> a special name for such M-chainable functions, e.g. "M-action functions"
> (whatever the M).
>

Technically they cannot be functions - there's no "same input, same output"
(at least not for input operations).  No referential transparency.  That's
the problem.


> >
> > This was a big problem for me; I find terms
> like "action", "computation", "function" completely misleading for IO
> terms/values.
>
>
> Why? A function of type (a -> M b) is a function that returns a value, (::
> M
> b), tagged with some monadic hidden data. In case of IO, it is a promise to
>
>
perform some actual I/O that's passed around, hidden. But the M-action
> function
> itself is just a regular Haskell function. It can be defined elsewhere,
> anywhere.
>

But the "promise to perform" is a matter of evaluation semantics, not
denotational semantics.  Denotationally these things cannot be functions.

I saw your other note too.  I think the idea that the runtime builds a
"future log" is useful - simple and pretty easy to grok.  But I would
recommend keeping a clear distinction between Haskell's language semantics
(denotational) and its compiler/runtime semantics (evaluational).
Denotationally, all a monad does is ensure sequencing, which is necessary to
properly order the (non-deterministic) IO values.  With lazy eval this gets
translated into the building of a "future log" etc.

Thanks,

-gregg
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20090302/a21f797c/attachment-0001.htm

------------------------------

Message: 4
Date: Mon, 2 Mar 2009 15:16:33 +0000 (UTC)
From: Will Ness <will_...@yahoo.com>
Subject: [Haskell-beginners] Re: clarification on IO
To: beginners@haskell.org
Message-ID: <loom.20090302t135627-...@post.gmane.org>
Content-Type: text/plain; charset=utf-8

Gregg Reynolds <dev <at> mobileink.com> writes:

> 
> 
> On Sun, Mar 1, 2009 at 11:59 AM, Will Ness <will_n48 <at> yahoo.com> wrote:
> 
>  
> 
> The IO-action is not the I/O operation in the real world, but an action of
> recording a promise to perform it.
> Any IO primitive can be seen as latching this hidden promise onto its explicit
> return value, thus creating a monadic value (:: IO a), carrying along this
> hidden promise. IO bind combines these promises into a combined record, or 
log,
> of promises to perform actual I/O activity, if called upon by the system.
> That recording of a promise is the IO-action that IO monad is about, from pure
> Haskell standpoint.
> 
> 
> Ok, I kinda like the idea of accumulating a "log" of promised actions, 
although I'd suggest a different term since log usually means history.  Maybe 
antilog or prelog or future trace or the like.  In any case, I think that's 
useful for explaining lazy evaluation, but it's not directly implicated by 
monad semantics.  IOW monad semantics and evaluation strategy are (mostly) 
orthogonal. 
> 
>  
> 
> Another monad will have another meaning for its actions, latching another
> hidden data on their results, but they still can be seen as actions, in 
context
> of being sequenced and combined by that monad's bind.
> 
> 
> I see, you're thinking of action as something like the promised eval.  As 
opposed to the action of performing actual IO.  I fear that might confuse 
newcomers, though; probably better to stick with "function" terminology and 
discuss evaluation separately. 
> 
> 
> 
> > Correction:  special name for IO "functions" (actually "IO terms" would be
> better). 
> Why? They are just fuctions, of type (Monad m => a -> m b). What I'm saying,
> they are of special type, chainable by the M monad, so it seems logical to 
have
> a special name for such M-chainable functions, e.g. "M-action functions"
> (whatever the M).
> 
> 
> Technically they cannot be functions - there's no "same input, same output" 
(at least not for input operations).  No referential transparency.  That's 
the 
problem. 
> 
> >
> > This was a big problem for me; I find terms
> like "action", "computation", "function" completely misleading for IO
> terms/values. 
> Why? A function of type (a -> M b) is a function that returns a value, (:: M
> b), tagged with some monadic hidden data. In case of IO, it is a promise to 
> 
> 
> perform some actual I/O that's passed around, hidden. But the M-action 
function
> itself is just a regular Haskell function. It can be defined elsewhere,
> anywhere.
> 
> 
> But the "promise to perform" is a matter of evaluation semantics, not 
denotational semantics.  Denotationally these things cannot be functions.I saw 
your other note too.  I think the idea that the runtime builds a "future log" 
is useful - simple and pretty easy to grok.  But I would recommend keeping a 
clear distinction between Haskell's language semantics (denotational) and its 
compiler/runtime semantics (evaluational).  Denotationally, all a monad does 
is 
ensure sequencing, which is necessary to properly order the (non-deterministic) 
IO values.  With lazy eval this gets translated into the building of a "future 
log" etc.Thanks,-gregg
> 
> 
> 
> 
> _______________________________________________
> Beginners mailing list
> Beginners <at> haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
> 






------------------------------

Message: 5
Date: Mon, 2 Mar 2009 15:21:28 +0000 (UTC)
From: Will Ness <will_...@yahoo.com>
Subject: [Haskell-beginners] Re: clarification on IO
To: beginners@haskell.org
Message-ID: <loom.20090302t135627-...@post.gmane.org>
Content-Type: text/plain; charset=utf-8

(something happened with my previous attempt to post, my apologies)

Gregg Reynolds <dev <at> mobileink.com> writes:

> 
> 
> On Sun, Mar 1, 2009 at 11:59 AM, Will Ness <will_n48 <at> yahoo.com> wrote:
> 
>  
> 
> The IO-action is not the I/O operation in the real world, but an action of
> recording a promise to perform it.
> 
> 
> Ok, I kinda like the idea of accumulating a "log" of promised actions, 
although I'd suggest a different term since log usually means history.  

It is a log of history of promises _requested_.

Or it can be a plan then. An operational record. A list. :)


>Maybe antilog or prelog or future trace or the like.  In any case, I think 
that's useful for explaining lazy evaluation, but it's not directly implicated 
by monad semantics.  IOW monad semantics and evaluation strategy are (mostly) 
orthogonal. 


I don't follow. Monad semantics in general is to chain together its action-
functions (:: a -> M b). IO monad's semantics is that it promises to perform 
the recorded requests, if called upon. Not only is it directly implicated by 
its semantics, it IS its semantics. It is what IO-bind is. Other monad's binds 
will mean something else.

We really ought to look at IO monad as just another kind of regular Haskell 
monad first.

Here your idea from the blog helps, of separating the two worlds, of compiler 
and of its run-time system implementation (in my re-formulation). The 
operational plan built by IO monad may have multiple entries interspersed, 
going back and force to one world or another (getting new input into its 
placeholder and then going into Haskell to perform a chunk of pure computation 
with it, then possibly going back for another input etc.). 

Or in case of output only of known in advance values it can be compiled down to 
just one output instruction. Which is recorded and stored in an (:: IO a) 
value. Which can be run SEVERAL times by the run-time, or none at all.

It's really helpful to imagine this operational plan as just a symbolic list of 
operations to be performed by some interpreter, capable of taking input, and 
calling back into Haskell code with it. The next step is to imagine it compiled 
into some kind of C with set-once semantics.

To recapture, the only difference IO monad has, is that it refers EXPLICITLY to 
a compiler, and its runtime execution operations. But from inside Haskell it's 
just anther monad (I've said that already haven't I? :) ).


>> Another monad will have another meaning for its actions, latching another
>> hidden data on their results, but they still can be seen as actions, in 
>> context
>> of being sequenced and combined by that monad's bind.
> 
> 
> I see, you're thinking of action as something like the promised eval. 

It is an action of entering a request (for future I/O activity) to be recorded 
by Haskell, to be performed later by its run-time system (notice I avoid the 
word evaluated which is confusing as it alludes back to the Haskell-world 
calculations). It _is_ the meaning of IO-action-function's associated ...well, 
action. 

> As opposed to the action of performing actual IO.  I fear that might confuse 
newcomers, though; probably better to stick with "function" terminology and 
discuss evaluation separately. 

That's why I propose to call these bind-chainable functions action functions, 
not just actions, and actual I/O acivities to call just that, activity. Also 
notice I write I/O there where it belongs to the actual world action (... the 
terminology really MUST be refined here!). I think anything else is confusing.

I'm open for another suggestion for how to name these "action-functions", but 
it's time the definite name is finalized; it's very confusing to see these IO-
action-functions referred to, in all these tutorials, as performing real world 
I/O actions. They don't, of course.

Better to avoid "evaluation" altogether (that seems to be your another idea 
from that log, is it?). 

I think the KEY is to always keep a clear separation of what is inside the pure 
Haskell world, and what is executed by its run-time, as an imperative program 
iving inside the real volatile world (capable of calling back into Haskell). 

And when inside the pure Haskell world, IO monad is ABSOLUTELY in NO RESPECT no 
different than any other. The operational log metaphor help keep this part of 
its semantics clear, from the other part - the fact that its operational log 
will actually get executed by run-time.


>> > Correction:  special name for IO "functions" (actually "IO terms" would be
>> > better). 
>> Why? They are just fuctions, of type (Monad m => a -> m b). What I'm saying,
>> they are of special type, chainable by the M monad, so it seems logical to 
>> have
>> a special name for such M-chainable functions, e.g. "M-action functions"
>> (whatever the M).
> 
> 
> Technically they cannot be functions - there's no "same input, same output" 
(at least not for input operations). 

Yes there is. There's the whole point I'm driving at. We are not performing a 
computation with our code. We describe the computation that will be performed. 
Our values are functions. The usage of actual input is deferred to the runtime 
system.

It's just like Show functions that (will) add their output onto a hidden 
parameter, the string-being-built (when called). Same here, with the log-being-
built. Assentially, we're dealing here with the delayed application of carried 
functions, that's all.

Here's again a simple outline of how an IO monad might look like, inside 
Haskell. It helped clarify things for me (dealing with output only, but still):

________________________________
data IO a = IORec -> (a,IORec) 
-- building the record of I/O activities to be performed

instance Monad IO where
  return a rec = (a,rec)            -- return :: a -> IO a
  (m »= g) rec = uncurry g $ m rec  -- g      :: a -> IO b

putStrLn :: a -> IO ()
putStrLn a rec = ((),rec ++ [("putStrLn", a)])
================================


> No referential transparency.  That's the problem. 

Everything is referentially transparent. There are no side effects in Haskell. 
You know that. :) You wrote as much yourself (assuming you're the author of 
that blog).
_______________________________________
IO value describes the computation that
WILL BE performed OUTSIDE of Haskell.
=======================================

That is a statement that is easy to understand, and is not at all confusing. I 
think.


>> > This was a big problem for me; I find terms
>> like "action", "computation", "function" completely misleading for IO
>> terms/values. 
>> Why? A function of type (a -> M b) is a function that returns a value, (:: M
>> b), tagged with some monadic hidden data. In case of IO, it is a promise to 
>> perform some actual I/O that's passed around, hidden. But the M-action 
>> function
>> itself is just a regular Haskell function. It can be defined elsewhere,
>> anywhere.
> 
> 
> But the "promise to perform" is a matter of evaluation semantics, not 
denotational semantics.  Denotationally these things cannot be functions.

But they are. They describe future computation to be performed outside of 
Haskell. Their values - inside Haskell - are one and the same - it's (:: IO a) 
entities. Which encapsulate the record, the 
_sceleton_of_future_computation_to_be_performed, which is ONE and only. It's 
just that it has holes in it, where the actual values will go into. It's like 
back into Prolog with its yet-unassigned variables. Or to any imperative 
language with set-once.


>I saw your other note too.  I think the idea that the runtime builds a "future 
log" is useful - simple and pretty easy to grok.  But I would recommend keeping 
a clear distinction between Haskell's language semantics (denotational) and its 
compiler/runtime semantics (evaluational).  

I think we've established that compiler and runtime should be kept completely 
separate.

>Denotationally, all a monad does is ensure sequencing, which is necessary to 
properly order the (non-deterministic) IO values.  

No it does more than that. It ascribes actual meaning to what its M-action-
functions mean, and it defines what it means for them to be combined in a 
chain. They are of course kept in sequence, in that chain.

>With lazy eval this gets translated into the building of a "future log" etc.

Right, only better not to use "eval" - ever. Haskell has expressions which get 
reduced; values belong to its runtime system. They are OUTSIDE of Haskell 
world. 

We do not "evaluate" anything. It would be an imperative. :)




> Thanks,-gregg


Thank you, for a great and enlightening discussion.

> 
> _______________________________________________
> Beginners mailing list
> Beginners <at> haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
> 




------------------------------

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 9, Issue 3
***************************************

Reply via email to