Re: [Haskell-cafe] Hackage 2 now available for beta testing

2013-09-12 Thread Andreas Abel
]
 
 Contributing to
the development
 ===
 
 The code is on
github and we welcome pull requests.
 
 There are open tickets
describing existing bugs and features that we
 want or that are in need
of improvement. Help on any of these would be
 greatly appreciated.


 There is some developer and user documentation on the github wiki,

including a quick guide to getting your own server instance up and

running.
 
 You can ask questions on the cabal-devel mailing list or
on IRC in
 the #hackage channel on freenode.
 
 [code]:
https://github.com/haskell/hackage-server [4]
 [github wiki]:
https://github.com/haskell/hackage-server/wiki [7]
 [cabal-devel]:
http://www.haskell.org/mailman/listinfo/cabal-devel [8]

-- 
Andreas
Abel  Du bist der geliebte Mensch. 

Theoretical Computer Science,
University of Munich http://www.tcs.informatik.uni-muenchen.de/~abel/



Links:
--
[1] http://beta.hackage.haskell.org/
[2]
http://industry.haskell.org/
[3]
https://github.com/haskell/hackage-server/issues
[4]
https://github.com/haskell/hackage-server
[5]
http://hackage.haskell.org/packages/archive
[6]
http://beta.hackage.haskell.org/new-features
[7]
https://github.com/haskell/hackage-server/wiki
[8]
http://www.haskell.org/mailman/listinfo/cabal-devel
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: New syntax for Haskell

2013-09-12 Thread Andreas Abel
 

+1 

Cucumber seems to be great if you mainly want to read your code
over the telephone, distribute it via national radio broadcast, or
dictate it to your secretary or your voice recognition software. You can
program thus without having to use you fingers. You can lie on your back
on your sofa, close your eyes, and utter your programs... 

We could
have blind Haskell/Cucumber programming contests... 

Tons of new
possiblilities... 

Strongly support this proposal. ;-) 

Andreas 

On
2013-09-10 22:57, Artyom Kazak wrote: 

 On Wed, 11 Sep 2013 00:20:26
+0400, Thiago Negri evoh...@gmail.com wrote:
 
 I hope these jokes
do not cause people to be afraid to post new ideas.
 
 Agreed. I would
also like to clarify that my message was much more a joke 
 on
 the
incomprehensibility of legal acts than on the original proposal.
 
 By
the way, I am pretty impressed with this piece of Cucumber 

description/code:
 
 Scenario: Mislav creates a valid task with an
upload
 When I go to the Awesome Ruby Yahh task list page of the
Ruby 
 Rockstars project
 When I follow + Add Task
 And I fill in
Task title with Ohhh upload
 And I follow Attachment
 When I
attach the file features/support/sample_files/dragon.jpg to 

upload_file
 And I press Add Task
 And I wait for 1 second
 And I
should see Ohhh upload as a task name
 
 I was much more sceptical
when I had only seen the example in Niklas's 
 message.

___
 Haskell-Cafe mailing
list
 Haskell-Cafe@haskell.org

http://www.haskell.org/mailman/listinfo/haskell-cafe [1]

-- 
Andreas
Abel  Du bist der geliebte Mensch. 

Theoretical Computer Science,
University of Munich http://www.tcs.informatik.uni-muenchen.de/~abel/



Links:
--
[1]
http://www.haskell.org/mailman/listinfo/haskell-cafe
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Some philosophy (Was: Alternative name for return)

2013-08-13 Thread Andreas Abel

On 09.08.2013 17:44, Jerzy Karczmarczuk wrote:

Indiscrete Thoughts by Gian-Carlo Rota, published by Birkhäuser in
1997. Available on the Web.


For download or to buy?  [This looks very interesting...]

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Alternative name for return

2013-08-13 Thread Andreas Abel

On 06.08.2013 10:46, Adam Gundry wrote:

On 06/08/13 06:14, J. Stutterheim wrote:

Suppose we now have the opportunity to change the name of the
`return` function in Monad, what would be a better  name for it?
(for some definition of better)


Rather than proposing a different name, I'm going to challenge the
premise of your question. Perhaps it would be better if `return` had no
name at all. Consider the following:

 return f `ap` s `ap` t

 f $ s * t

 do { sv - s
; tv - t
; return (f sv tv) }


Indeed, I wished the 0-ary case would be more alike to the unary and 
binary case, cf.


  return f0
  f1 $ a1
  f2 $ a1 * a2

What is needed is a nice syntax for idiom brackets.


These are all different ways of spelling

 f s t

plus the necessary applicative or monadic bureaucracy. But why couldn't
we write just the plain application, and let the type system deal with
the plumbing of effects?


I would not think this is practically possible.  For instance, if

  f :: a - b - c

then it could be a binary function or a unary function in the context 
monad reading from a, thus, application


  f x

is ambiguous or too sensitive, especially with type inference.


I realise that this may be too open a research area for your project...



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-08-02 Thread Andreas Abel

On 26.07.13 6:44 PM, Andreas Abel wrote:

headers0 - M.fromList $ do
  forM fields_header $ \ (n, fld) - do
(n,) $ reflect $ fld ast


Ah, I forgot one more 'do' to override the stronger binding of $:

  (n,) $ do reflect $ fld ast


Great satisfaction!  I killed all long-ranging parentheses! ;-)

-- Andreas


   let headers = M.insert _report_ranges (format_two_tstamps rv)
headers0
   foldM write_period (rv,headers,(snd rv,snd rv)) asts
   return ()
  where
  write_period (rv,headers,mv) ast = do
   pv@(p_valid_from,p_valid_until) - reflect $ get_trange TRange ast
   check_inside pv rv
   let prevailing = M.lookup PREVAILING ast
   (mv,pv) - case prevailing of
 Just _  - return (pv,pv)-- set the major valid period
 -- Make sure each VAR period occurs later than the prevailing
 -- period. If exactly at the same time add 1 min
 Nothing - case () of
  _ | fst mv  p_valid_from  - return (mv,pv)
  _ | fst mv == p_valid_from - return (mv,(p_valid_from + 60,
  p_valid_until))
  _  - gthrow . InvalidData . unwords $ [
   VAR period begins before prevailing:,
  show ast, ; prevailing TRange, show mv]
   let token  = maybe (M.findWithDefault  VAR ast) id prevailing
   let ast1 = M.insert _token token .
M.insert _period_valid (format_two_tstamps pv) .
  M.unionWith (\_ x - x) headers $ ast
   let title  = M.member Title ast
   let headers1 = if title then headers else
M.delete _limit_to  . M.delete _limit_recd $ headers

   write_fields h ast1 fields

   return (rv,headers1,mv)


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe






--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-26 Thread Andreas Abel
Mmh, true, for polymorphic definitions there is not a lot to see.  This 
probably diminishes the applicability of a strictness analysis quite a 
bit.  Maybe it is entirely useless at this point.


It would make more sense after whole-program optimization.  Ghc does not 
have this, I heard the Intel Research Compiler does such things.


This is becoming a very high-hanging fruit...

--Andreas

On 24.07.2013 20:22, Edward Kmett wrote:

You only have a Num constraint when type checking that code:

(+) :: Num a = a - a - a

For better or worse, you don't get strictness in the type signatures in
Haskell.

We do not separate codata from data here.

Without knowing about the particular instance of Num and even the
direction of recursion on (+) there is no information for such a
strictness analyzer to work with.

many :: Alternative m = m a - m [a]
many p = ps where
   ps = (:) $ p * ps
| pure []

is another perfectly cromulent example of value recursion, and one
that is far nearer and dearer to my heart and is similarly opaque to any
such analysis.

-Edward



On Wed, Jul 24, 2013 at 4:14 AM, Andreas Abel andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.de wrote:

Sure.  I have not looked a concrete strictness analyses, but I
expect they would treat Conat differently than Integer.  In particular,

   x   does *not* appear strictly in  S x

if S is a lazy constructor.


On 22.07.13 4:54 PM, Edward Kmett wrote:

let x = x +1

is perfectly cromulent when x is sufficiently lazy, e.g. in the
one point compactification of the naturals:

data Conat = S Conat | Z

There it represents infinity with proper sharing.

-Edward

On Jul 22, 2013, at 10:24 AM, Andreas Abel
andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de wrote:

On 22.07.2013 10:50, MigMit wrote:


On Jul 22, 2013, at 12:27 PM, Andreas Abel
andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de
wrote:

On 20.07.13 9:36 PM, Evan Laforge wrote:

However, I'm also not agitating for a
non-recursive let, I think
that ship has sailed.  Besides, if it were added
people would
start wondering about non-recursive where, and
it would introduce
an exception to haskell's pretty consistently
order-independent
declaration style.


For functions, recursive-by-default let makes sense.
  But for
*values*, intended recursion is rather the
exception.  It is useful
for infinite lists and the like.  For values of
atomic type like
Int or Bool, recursive let is a bug.


It seems hard to distinguish between them. What about
values that
contain functions, like data T = T Int (Int - Int)?
What about
polymorphic values, that could be functions and could be
not?


I agree.  It cannot be implemented like that.  A thing that
could be implemented is that

   let x = e

is an error if x appears strictly in e.  In practice, this
could catch some unintended cases of recursion like

   let x = x +1

, but not all of them.

Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~__abel/
http://www2.tcs.ifi.lmu.de/~abel/

_
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org mailto:Haskell-Cafe@haskell.org
http://www.haskell.org/__mailman/listinfo/haskell-cafe
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~__abel/ http://www2.tcs.ifi.lmu.de/~abel/





--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-26 Thread Andreas Abel

On 25.07.2013 09:09, o...@okmij.org wrote:


Here is a snippet from a real code that could benefit from
non-recursive let. The example is notable because it incrementally
constructs not one but two structures (both maps), ast and headers.
The maps are constructed in a bit interleaved fashion, and stuffing
them into the same State would be ungainly. In my real code

-- Add an update record to a buffer file
do_update :: String - Handle - Parsed - [Parsed] - IO ()
do_update TAF h ast asts@(_:_) = do
   rv - reflect $ get_trange TRange ast



   headers0 - return . M.fromList = sequence
  (map (\ (n,fld) - reflect (fld ast) = \v - return (n,v))
  fields_header)


This is a mouth-full.  The = \v - return (n,v) can be more 
elegantly expressed with tuple section


   (map (\ (n,fld) - (n,) $ reflect (fld ast)) fields_header)

Maybe even use

  mapSnd f = (id *** f)

and write

   (map (mapSnd $ \ fld - reflect (fld ast)) fields_header)

and, getting into lambda-killing rush :-)

   (map (mapSnd $ reflect . ($ ast)) fields_header)

(ok, now we overdid it).

Also, was not mapM = sequence . map ?
And  return . f = m   the same as f $ m?  Then we are at

   headers0 - M.fromList $ do
 mapM (\ (n,fld) - (n,) $ reflect (fld ast)) fields_header

Actually, I prefer for-loops:

   headers0 - M.fromList $ do
 forM fields_header $ \ (n, fld) - do
   (n,) $ reflect $ fld ast

Great satisfaction!  I killed all long-ranging parentheses! ;-)

-- Andreas


   let headers = M.insert _report_ranges (format_two_tstamps rv) headers0
   foldM write_period (rv,headers,(snd rv,snd rv)) asts
   return ()
  where
  write_period (rv,headers,mv) ast = do
   pv@(p_valid_from,p_valid_until) - reflect $ get_trange TRange ast
   check_inside pv rv
   let prevailing = M.lookup PREVAILING ast
   (mv,pv) - case prevailing of
 Just _  - return (pv,pv)   -- set the major valid period
 -- Make sure each VAR period occurs later than the prevailing
 -- period. If exactly at the same time add 1 min
 Nothing - case () of
  _ | fst mv  p_valid_from  - return (mv,pv)
  _ | fst mv == p_valid_from - return (mv,(p_valid_from + 60,
  p_valid_until))
  _  - gthrow . InvalidData . unwords $ [
   VAR period begins before prevailing:,
  show ast, ; prevailing TRange, show mv]
   let token  = maybe (M.findWithDefault  VAR ast) id prevailing
   let ast1 = M.insert _token token .
M.insert _period_valid (format_two_tstamps pv) .
  M.unionWith (\_ x - x) headers $ ast
   let title  = M.member Title ast
   let headers1 = if title then headers else
M.delete _limit_to  . M.delete _limit_recd $ headers

   write_fields h ast1 fields

   return (rv,headers1,mv)


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] memoization

2013-07-24 Thread Andreas Abel

Sorry I screwed up.  The following is indeed memoizing:

fib5 :: Int - Integer
fib5 = \ x - fibs !! x
   where fibs = map fib [0 ..]
 fib 0 = 0
 fib 1 = 1
 fib n = fib5 (n-2) + fib5 (n-1)

Here, the eta-expansion does not matter.  But as you say, memoized_fib 
below is not memoizing, since x is in scope in the where clauses, even 
though they do not mention it.  Thus, for each x we get new 
definitions of fibs and fib.  Yet, this is only true for -O0.


For -O1 and greater, ghc seems to see that x is not mentioned in the 
where clauses and apparently lifts them out.  Thus, for -O1.. 
memoized_fib is also memoizing.  (I ran it, this time ;-) !)


Cheers,
Andreas

On 22.07.13 11:43 PM, Tom Ellis wrote:

On Mon, Jul 22, 2013 at 04:16:19PM +0200, Andreas Abel wrote:

In general, I would not trust such compiler magic, but just let-bind
anything I want memoized myself:

memoized_fib :: Int - Integer
memoized_fib x = fibs !! x
 where fibs  = map fib [0..]   -- lazily computed infinite list
   fib 0 = 0
   fib 1 = 1
   fib n = memoized_fib (n-2) + memoized_fib (n-1)

The eta-expansions do not matter.


I meant to write

  Then, eta-expansions do not matter.

(In general, they do matter.)


But this is *not* memoized (run it and see!).  The eta-expansions do
indeed matter (although I don't think they are truly eta-expasions because
of the desugaring of the where to a let).

What matters is not the let binding, but where the let binding occurs in
relation to the lambda.  There's no compiler magic here, just operational
semantics.

Tom

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-24 Thread Andreas Abel

On 23.07.13 4:34 AM, Richard A. O'Keefe wrote:


On 22/07/2013, at 8:14 PM, Andreas Abel wrote:


Just today, my student asked me why the following program does nothing:


Did you ask your student why their code should not be torn into pieces,
burned to ashes, and incorporated into a pot for radioactive waste?

All those occurrences of unsafePerformIO!


No, here they are intended, to simulate something like uniqueness types 
in Clean, which incidentially has been mentioned on this thread before.


The loop has nothing to do with unsafePerformIO, but stems from 
Haskell's idiosyncratic recursive let, which is a trap for all that come 
from another functional language.


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-24 Thread Andreas Abel
Sure.  I have not looked a concrete strictness analyses, but I expect 
they would treat Conat differently than Integer.  In particular,


  x   does *not* appear strictly in  S x

if S is a lazy constructor.

On 22.07.13 4:54 PM, Edward Kmett wrote:

let x = x +1

is perfectly cromulent when x is sufficiently lazy, e.g. in the one point 
compactification of the naturals:

data Conat = S Conat | Z

There it represents infinity with proper sharing.

-Edward

On Jul 22, 2013, at 10:24 AM, Andreas Abel andreas.a...@ifi.lmu.de wrote:


On 22.07.2013 10:50, MigMit wrote:


On Jul 22, 2013, at 12:27 PM, Andreas Abel andreas.a...@ifi.lmu.de
wrote:


On 20.07.13 9:36 PM, Evan Laforge wrote:

However, I'm also not agitating for a non-recursive let, I think
that ship has sailed.  Besides, if it were added people would
start wondering about non-recursive where, and it would introduce
an exception to haskell's pretty consistently order-independent
declaration style.


For functions, recursive-by-default let makes sense.  But for
*values*, intended recursion is rather the exception.  It is useful
for infinite lists and the like.  For values of atomic type like
Int or Bool, recursive let is a bug.


It seems hard to distinguish between them. What about values that
contain functions, like data T = T Int (Int - Int)? What about
polymorphic values, that could be functions and could be not?


I agree.  It cannot be implemented like that.  A thing that could be 
implemented is that

  let x = e

is an error if x appears strictly in e.  In practice, this could catch some 
unintended cases of recursion like

  let x = x +1

, but not all of them.

Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-22 Thread Andreas Abel

Just today, my student asked me why the following program does nothing:

{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, BangPatterns #-}

import Control.Monad
import System.IO.Unsafe
import Data.Array.IO
import Data.IORef
import Debug.Trace


type LinearArray a = (Int, IORef Int, IOArray Int a)

initLinearArray :: Int - a - LinearArray a
initLinearArray l a =
  trace init (
   unsafePerformIO (do version - newIORef 0
   array - newArray (0, l - 1) a
   return (0, version, array)))

readLinearArray :: Int - (LinearArray a) - a
readLinearArray l !(ver, realver, arr) =
  trace read (
   unsafePerformIO (do version - readIORef realver
   element - readArray arr l
   if (version == ver) then
 return element
 else error Non-Linear read of linear Array))

writeLinearArray :: Int - a - LinearArray a - LinearArray a
writeLinearArray l e !(ver, realver, arr) =
  trace write (
   unsafePerformIO (do version - readIORef realver
   if (version == ver)
 then
 do writeIORef realver $ ver + 1
writeArray arr l e
return (ver + 1, realver, arr)
 else error Non-Linear write of linear Array))

linearArrayToList :: Int - Int - (LinearArray a) - [a]
linearArrayToList c m !a =
  trace toList (
if (c = m) then []
else (readLinearArray c a) : (linearArrayToList (c + 1) m a))

eratostenesTest :: Int - [Bool]
eratostenesTest length =
  let
strikeMult :: Int - Int - Int - (LinearArray Bool) - 
(LinearArray Bool)

strikeMult div cur len arr = trace smStart (
  if (cur = len)
  then trace arr arr
  else let arr = trace write $ writeLinearArray cur False arr
   in trace strikeMult2 $ strikeMult div (cur + div) len arr)
nextPrime :: Int - Int - (LinearArray Bool) - (LinearArray Bool)
nextPrime cur len !arr =
  if (cur = len)
  then
arr
  else if (readLinearArray cur arr)
   then
 let arr = trace strikeMult $ strikeMult cur (cur + cur) 
len arr

 in trace nextPrime $ nextPrime (cur + 1) len arr
   else
 nextPrime (cur + 1) len arr
ini = trace ini (initLinearArray length True)
theArray = trace nextPrimeCall $ nextPrime 2 length ini
  in
   linearArrayToList 0 length theArray

On 22.07.13 9:01 AM, Richard A. O'Keefe wrote:


On 21/07/2013, at 7:36 AM, Evan Laforge wrote:

Just by coincidence, I recently wrote this:


This is a BEAUTIFUL example.
I think we may disagree about what it's an example OF,
however.  I found the code a little difficult to
follow, but when that's fixed up, there's no longer
any reason to want non-recursive let, OR a monad.

I've run out of time tonight, but hope to say more tomorrow.


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-22 Thread Andreas Abel

On 20.07.13 9:36 PM, Evan Laforge wrote:

However, I'm also not agitating for a non-recursive let, I think that
ship has sailed.  Besides, if it were added people would start
wondering about non-recursive where, and it would introduce an
exception to haskell's pretty consistently order-independent
declaration style.


For functions, recursive-by-default let makes sense.  But for *values*, 
intended recursion is rather the exception.  It is useful for infinite 
lists and the like.  For values of atomic type like Int or Bool, 
recursive let is a bug.


Of course, if you want to do scope-checking before type-checking, which 
also makes sense, you cannot make recursiveness type-dependent.


Distinguishing 'let' into 'fun', 'val' and 'val rec' could help here:

Non-recursive:

  val x = e
  in  e'

Recursive:

  fun f x = e
  in  e'

  val rec x = e(x)
  in  e'

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] memoization

2013-07-22 Thread Andreas Abel

On 22.07.2013 09:52, Chris Wong wrote:

memoized_fib :: Int - Integer
memoized_fib = (map fib [0 ..] !!)
where fib 0 = 0
  fib 1 = 1
  fib n = memoized_fib (n-2) + memoized_fib (n-1)



[.. snipped ..]


Could someone explain the technical details of why this works? Why is map
fib [0 ..] not recalculated every time I call memoized_fib?


A binding is memoized if, ignoring everything after the equals sign,
it looks like a constant.

In other words, these are memoized:

 x = 2

 Just x = blah

 (x, y) = blah

 f = \x - x + 1
 -- f = ...

and these are not:

 f x = x + 1

 f (Just x, y) = x + y

If you remove the right-hand side of memoized_fib, you get:

 memoized_fib = ...

This looks like a constant. So the value (map fib [0..] !!) is memoized.

If you change that line to

 memoized_fib x = map fib [0..] !! x

GHC no longer memoizes it, and it runs much more slowly.


True, but the essential thing to be memoized is not memoized_fib, which 
is a function, but the subexpression


  map fib [0..]

which is an infinite list, i.e., a value.

The rule must be like in

  let x = e

if e is purely applicative, then its subexpressions are memoized.
For instance, the following is also not memoizing:

fib3 :: Int - Integer
fib3 = \ x - map fib [0 ..] !! x
   where fib 0 = 0
 fib 1 = 1
 fib n = fib3 (n-2) + fib3 (n-1)

In general, I would not trust such compiler magic, but just let-bind 
anything I want memoized myself:


memoized_fib :: Int - Integer
memoized_fib x = fibs !! x
where fibs  = map fib [0..]   -- lazily computed infinite list
  fib 0 = 0
  fib 1 = 1
  fib n = memoized_fib (n-2) + memoized_fib (n-1)

The eta-expansions do not matter.

Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-22 Thread Andreas Abel

On 22.07.2013 10:50, MigMit wrote:


On Jul 22, 2013, at 12:27 PM, Andreas Abel andreas.a...@ifi.lmu.de
wrote:


On 20.07.13 9:36 PM, Evan Laforge wrote:

However, I'm also not agitating for a non-recursive let, I think
that ship has sailed.  Besides, if it were added people would
start wondering about non-recursive where, and it would introduce
an exception to haskell's pretty consistently order-independent
declaration style.


For functions, recursive-by-default let makes sense.  But for
*values*, intended recursion is rather the exception.  It is useful
for infinite lists and the like.  For values of atomic type like
Int or Bool, recursive let is a bug.


It seems hard to distinguish between them. What about values that
contain functions, like data T = T Int (Int - Int)? What about
polymorphic values, that could be functions and could be not?


I agree.  It cannot be implemented like that.  A thing that could be 
implemented is that


  let x = e

is an error if x appears strictly in e.  In practice, this could catch 
some unintended cases of recursion like


  let x = x +1

, but not all of them.

Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-18 Thread Andreas Abel

On 17.07.13 9:46 PM, Edward Kmett wrote:

FWIW, I maintain, according to wc and sloccount, 220841 lines worth of
Haskell code at present.


Thanks, this is great service to our community.  And you produce 
excellent quality!



I have been bitten this error one time, so it affects me .45% of the
time and that was only because it was in the only package I was not
using -Wall on.

-Edward

On Wed, Jul 17, 2013 at 12:23 PM, Andreas Abel andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.de wrote:

Here, again, is your ACTUAL CODE, commented, deployed, looping, and
maybe linked into your projects, if you are not careless about the
cabal constraints:


http://hackage.haskell.org/__packages/archive/mtl/2.1/doc/__html/src/Control-Monad-State-__Class.html#state

http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#state

 -- | Embed a simple state action into the monad.
 state :: (s - (a, s)) - m a
 state f = do
   s - get
   let ~(a, s) = f s
   put s
   return a

Have fun with it,
Andreas


On 17.07.2013 02:20, Richard A. O'Keefe wrote:

Brian Marick sent me a couple of his stickers.
The one I have on my door reads to be less wrong than yesterday.
The other one I keep free to bring out and wave around:

 An example would be handy about now.

All of the arguing to and fro -- including mine! -- about
non-recursive let has been just so much hot air.  I could
go on about how the distinction between 'val' and 'val rec'
in ML was one of the things I came to dislike intensely,
and how Haskell's single coherent approach is one of the
things that attracted me to Haskell.

But why should anyone else care?

When presented with a difficulty, it is very common for some
functional language users to propose adding just one more
feature from some other language, commonly an imperative one
(which ML, Caml, and F# arguably are).  Typically this is
something that _would_ solve the immediate problem but would
create worse problems elsewhere, and there is some other
solution, either one already available in the language, or a
better one that would solve additional problems or cause
fewer ones.

The best help for any discussion is A CONCRETE EXAMPLE OF
REAL CODE.  Not little sketches hacked up for the purpose
of discussion, but ACTUAL CODE.  The person who initially
proposes a problem may think some details are not relevant,
whereas someone else may see them as the key to the solution.

For example, looking at some code in another mostly-
functional language, which had been presented as reason why
we needed a new construct, I rewrote it in less than half
the number of lines using existing constructors, using only
existing features.

Without seeing THE ACTUAL CODE that prompted this thread,
it is impossible to tell whether that might be the case here.

In this specific case, we are seeing state being threaded
through a bunch of updates, and IN THE ABSENCE OF THE ACTUAL
CODE, it seems to me that monad notation is the most
intention-revealing notation available for the purpose in
Haskell, and if Haskell did have non-recursive let it would
STILL be best to write such code using a state monad so that
human beings reading the Haskell code would have some idea
of what was happening, because that's how state changes are
supposed to be expressed in Haskell, and anything else
counts as obfuscation.

But THE ACTUAL CODE might show that this case was different
in some important way.



_
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org mailto:Haskell-Cafe@haskell.org
http://www.haskell.org/__mailman/listinfo/haskell-cafe
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~__abel/ http://www2.tcs.ifi.lmu.de/~abel/

_
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org mailto:Haskell-Cafe@haskell.org
http://www.haskell.org/__mailman/listinfo/haskell-cafe
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel

Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-17 Thread Andreas Abel
Here, again, is your ACTUAL CODE, commented, deployed, looping, and 
maybe linked into your projects, if you are not careless about the cabal 
constraints:


http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#state

-- | Embed a simple state action into the monad.
state :: (s - (a, s)) - m a
state f = do
  s - get
  let ~(a, s) = f s
  put s
  return a

Have fun with it,
Andreas

On 17.07.2013 02:20, Richard A. O'Keefe wrote:

Brian Marick sent me a couple of his stickers.
The one I have on my door reads to be less wrong than yesterday.
The other one I keep free to bring out and wave around:

An example would be handy about now.

All of the arguing to and fro -- including mine! -- about
non-recursive let has been just so much hot air.  I could
go on about how the distinction between 'val' and 'val rec'
in ML was one of the things I came to dislike intensely,
and how Haskell's single coherent approach is one of the
things that attracted me to Haskell.

But why should anyone else care?

When presented with a difficulty, it is very common for some
functional language users to propose adding just one more
feature from some other language, commonly an imperative one
(which ML, Caml, and F# arguably are).  Typically this is
something that _would_ solve the immediate problem but would
create worse problems elsewhere, and there is some other
solution, either one already available in the language, or a
better one that would solve additional problems or cause
fewer ones.

The best help for any discussion is A CONCRETE EXAMPLE OF
REAL CODE.  Not little sketches hacked up for the purpose
of discussion, but ACTUAL CODE.  The person who initially
proposes a problem may think some details are not relevant,
whereas someone else may see them as the key to the solution.

For example, looking at some code in another mostly-
functional language, which had been presented as reason why
we needed a new construct, I rewrote it in less than half
the number of lines using existing constructors, using only
existing features.

Without seeing THE ACTUAL CODE that prompted this thread,
it is impossible to tell whether that might be the case here.

In this specific case, we are seeing state being threaded
through a bunch of updates, and IN THE ABSENCE OF THE ACTUAL
CODE, it seems to me that monad notation is the most
intention-revealing notation available for the purpose in
Haskell, and if Haskell did have non-recursive let it would
STILL be best to write such code using a state monad so that
human beings reading the Haskell code would have some idea
of what was happening, because that's how state changes are
supposed to be expressed in Haskell, and anything else
counts as obfuscation.

But THE ACTUAL CODE might show that this case was different
in some important way.



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ordNub

2013-07-16 Thread Andreas Abel

On 14.07.2013 13:20, Niklas Hambüchen wrote:

I've taken the Ord-based O(n * log n) implementation from yi using a Set:

   ordNub :: (Ord a) = [a] - [a]
   ordNub l = go empty l
 where
   go _ [] = []
   go s (x:xs) = if x `member` s then go s xs
 else x : go (insert x s) xs

(The benchmark also shows some other potential problem: Using a state
monad to keep the set instead of a function argument can be up to 20
times slower. Should that happen?)


I cannot say whether this should happen, but your code about can be 
straight-forwardly refactored using a *Reader* monad.


import Control.Monad.Reader

import Data.Functor (($))
import qualified Data.Set as Set

-- ifM still not in Control.Monad
ifM mc md me = do { c - mc; if c then md else me }

ordNub :: (Ord a) = [a] - [a]
ordNub l = runReader (go l) Set.empty
  where
go [] = return []
go (x:xs) = ifM ((x `Set.member`) $ ask)
(go xs)
((x :) $ local (Set.insert x) (go xs))

test = ordNub [1,2,4,1,3,5,2,3,4,5,6,1]

Of course, this does not lend itself to an application of filterM.

In fact, your implementation is already in the (Set a -) reader monad, 
in normalized form.  It looks already optimal to me.


Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-16 Thread Andreas Abel

Ah, now I have the solution:

{-# LANGUAGE CPP #-}

(|) = flip ($)

#define LET(p, e) (e) | \ (p) -

bla = LET(x, 5)
  LET(Just x, Just (x+1))
  x

#define MLET(p, e) (e) | \ (p) - do

main = do
  MLET((x, y), (5, 3))
  print (x + y)

Beautiful, ain't it?  Sigh.

--Andreas

On 11.07.2013 17:40, Carter Schonwald wrote:

Yup. Nested cases *are* non recursive lets.

(Can't believe I forgot about that )

On Thursday, July 11, 2013, Edward Kmett wrote:


blah = case foo 1 [] of
   (x, s) - case bar x s of
  (y, s) - case baz x y s of
(z, s) - ...

-Edward



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guards loops]

2013-07-12 Thread Andreas Abel

On 12.07.2013 02:22, Richard A. O'Keefe wrote:

For what it's worth,


let x = 1 in

-   let x = x+1 in
- let x = x+2 in
-   x;;

prints

val it : int = 4

in the F# interactive system, but


let x = 1 in

- let x = x+1 in
- let x = x+2 in
-   x;;

prints Duplicate definition of x at the second line.


Since silverlight does not work properly on my systems, I cannot 
tryfsharp.org.  I can try ocaml, which does not use indentation, and 
there the value is 4, and there is no ambiguity at all.


  let p = e in body

is just

  (\ p - body) e

it cannot be simpler than that.  So I do not see your point.

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let

2013-07-11 Thread Andreas Abel

Note that for non-recursive lets

  let' x1 = e1
   x2 = e2

is sequential and *not* the same as the parallel

  let' (x1, x2) = (e1, e2)

The first is

  (\ x1 - (\x2 - ...) e2) e1

and the second is

  (\ (x1,x2) - ...) (e1, e2)

On 11.07.2013 13:36, Doug McIlroy wrote:

By analogy to ML, which has let and let rec, where the latter
corresponds to Haskell's let, one is led to let nonrec. I
would definitely not like shadow, for it means that new
variable does NOT cast a shadow on its definining expression.

I fear also that let nonrec by any name would introduce another
attractive nuisance, just as insidious as the one it is intended
to correct. For example
 x = ...
 let nonrec { x = someFunction x
  xsq = x^2} in ...
won't do what was probably intended. In my own code, this idiom
is more likely than the one that sparked the discussion.

Doug

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-11 Thread Andreas Abel

I can do this without extra indentation:

  (|) = flip ($)

  f = 5 | \ x -
  6 | \ y -
  x + y

Non-recursive let is as superfluous as the do-notation.

On 11.07.2013 17:40, Carter Schonwald wrote:

Yup. Nested cases *are* non recursive lets.

(Can't believe I forgot about that )

On Thursday, July 11, 2013, Edward Kmett wrote:

On Wed, Jul 10, 2013 at 3:47 AM, o...@okmij.org javascript:_e({},
'cvml', 'o...@okmij.org'); wrote:


Jon Fairbairn wrote:
  It just changes forgetting to use different variable names
because of
  recursion (which is currently uniform throughout the language) to
  forgetting to use non recursive let instead of let.

Let me bring to the record the message I just wrote on Haskell-cafe
http://www.haskell.org/pipermail/haskell-cafe/2013-July/109116.html

and repeat the example:

In OCaml, I can (and often do) write

 let (x,s) = foo 1 [] in
 let (y,s) = bar x s in
 let (z,s) = baz x y s in ...

In Haskell I'll have to uniquely number the s's:

 let (x,s1)  = foo 1 [] in
 let (y,s2)  = bar x s1 in
 let (z,s3)  = baz x y s2 in ...

and re-number them if I insert a new statement.


blah = case foo 1 [] of
   (x, s) - case bar x s of
  (y, s) - case baz x y s of
(z, s) - ...

-Edward



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guards loops]

2013-07-10 Thread Andreas Abel

Hi Oleg,

just now I wrote a message to haskell-pr...@haskell.org to propose a 
non-recursive let.  Unfortunately, the default let is recursive, so we 
only have names like let' for it.  I also mentioned the ugly workaround 
(- return $) that I was shocked to see the first time, but use myself 
sometimes now.


Cheers,
Andreas

On 10.07.2013 09:34, o...@okmij.org wrote:

Andreas wrote:

The greater evil is that Haskell does not have a non-recursive let.
This is source of many non-termination bugs, including this one here.
let should be non-recursive by default, and for recursion we could have
the good old let rec.


Hear, hear! In OCaml, I can (and often do) write

 let (x,s) = foo 1 [] in
 let (y,s) = bar x s in
 let (z,s) = baz x y s in ...

In Haskell I'll have to uniquely number the s's:

 let (x,s1)  = foo 1 [] in
 let (y,s2)  = bar x s1 in
 let (z,s3)  = baz x y s2 in ...

and re-number them if I insert a new statement. BASIC comes to mind. I
tried to lobby Simon Peyton-Jones for the non-recursive let a couple
of years ago. He said, write a proposal. It's still being
written... Perhaps you might want to write it now.

In the meanwhile, there is a very ugly workaround:

 test = runIdentity $ do
  (x,s) - return $ foo 1 []
  (y,s) - return $ bar x s
  (z,s) - return $ baz x y s
  return (z,s)

After all, bind is non-recursive let.






--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guards loops]

2013-07-10 Thread Andreas Abel

On 10.07.2013 10:16, Ertugrul Söylemez wrote:

o...@okmij.org wrote:


Hear, hear! In OCaml, I can (and often do) write

 let (x,s) = foo 1 [] in
 let (y,s) = bar x s in
 let (z,s) = baz x y s in ...

In Haskell I'll have to uniquely number the s's:

 let (x,s1)  = foo 1 [] in
 let (y,s2)  = bar x s1 in
 let (z,s3)  = baz x y s2 in ...


This isn't a case for non-recursive let.  It is one of the rare cases
where you might actually consider using a state monad.


Except when you are implementing the state monad (giggle):


http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#state


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guardsloops]

2013-07-10 Thread Andreas Abel

Totality checking will generate a lot of false positives.

One would like an analysis that prints an error message if an expression 
is *definitely* looping in all cases.  While I have studied termination, 
I have not studied non-termination analyses.  It is harder than 
termination.  For termination checking, you can over-approximate the 
control-flows and just scream if you find a *potential* control flow 
that *might* lead to non-termination.  If you do not find such a control 
flow you can be sure things are terminating.  This is how Agda does it.


To be sure that something is definitely non-terminating, you need to 
show it is non-terminating on all *actual* control flows.  But usually 
you cannot statically tell whether in if c then d else e d or e is 
evaluated, so a non-termination analysis without false positives seems 
very restricted.  Still it might be could useful.


Having said this, having a termination analysis is not the proper 
solution to the lack of a non-recursive let, it does not establish 
shadowing behavior I want.


Cheers,
Andreas

On 10.07.13 7:44 PM, Ertugrul Söylemez wrote:

Donn Cave d...@avvanta.com wrote:


Let is recursive because, unlike in the case of other languages,
variables are not locations for storing values, but the expressions
on the right side of the equality themselves. And obviously it is
not possible for a variable-expression to be two expressions at the
same time. The recursiveness is buildt-in. It comes from its pure
nature.


I'm surprised that it would come down to purity.  It looks to me like
simply a question of scope.  I had to write an example program to see
what actually happens, because with me it isn't intuitive at all
that the name bound to an expression would be visible from within
the expression itself.  I suppose this is considered by some to be a
feature, obviously to others it's a bug.


In a non-strict-by-default language like Haskell it's certainly a
feature.  A sufficiently smart compiler can figure out whether a
definition is recursive or not and apply the proper transformation, so
from a language-theoretic standpoint there is really no reason to have a
non-recursive let.

I think the proper solution is to identify the underlying problem:
general recursion.  Haskell does not enforce totality.  I'd really love
to see some optional totality checking in Haskell.  If Oleg decides not
to use a state monad, he will still have to be careful not to confuse
the numbers, but if he does, then the compiler will reject his code
instead of producing looping code.


Greets,
Ertugrul



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Proposal: Non-recursive let

2013-07-10 Thread Andreas Abel

On 10.07.13 9:31 PM, Carter Schonwald wrote:

theres a very simple way to do non recursive let already! do notation in
the identity monad. I use it quite a lot lately.


Yeah, the hack

  x - return $ e

instead of

  let x = e

has been discussed already.

If you put everything into the Identity monad, you lose if-then-else and 
direct use of case, instead of


  case me of {branches }

you need to write

   e - me; case e of { branches }

This gets a bit better with the new \case, if you can afford to only 
compile on the newest ghc.


  me = \case { branches }



On Wed, Jul 10, 2013 at 1:49 PM, Ertugrul Söylemez e...@ertes.de
mailto:e...@ertes.de wrote:

Ezra e. k. Cooper e...@ezrakilty.net mailto:e...@ezrakilty.net
wrote:

  As starter suggestions for the keyword or syntax, I submit:
 
let new x = expr in body   -- Not the old x!

It's not the old x in either case (recursive and non-recursive).


let shadowing x = expr in body
 
shadow x = expr in body

It's shadowing in either case.


let x =! expr in body  -- The explosive bang gives an imperative
flavor.

(=!) is a valid operator name.


  Other suggestions would be welcome.

My suggestion:  Don't add a non-recursive let.  See my other post about
general recursion and totality checking.


Greets,
Ertugrul

--
Not to be or to be and (not to be or to be and (not to be or to be and
(not to be or to be and ... that is the list monad.



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guardsloops]

2013-07-10 Thread Andreas Abel

On 10.07.13 6:00 PM, Donn Cave wrote:

quoth Alberto G. Corona,


Let is recursive because, unlike in the case of other
languages, variables are not locations for storing values, but the
expressions on the right side of the equality themselves. And obviously it
is not possible for a variable-expression to be two expressions at the same
time. The recursiveness is buildt-in. It comes from its pure nature.


@Alberto: you must have misunderstood my proposal.


I'm surprised that it would come down to purity.  It looks to me like
simply a question of scope.  I had to write an example program to see
what actually happens, because with me it isn't intuitive at all that
the name bound to an expression would be visible from within the
expression itself.  I suppose this is considered by some to be a feature,
obviously to others it's a bug.


Value-recursion *is* useful in a lazy language, e.g.

  let xs = 0 : xs

builds an infinite (in fact, circular) list of 0s.  But it is not always 
meaningful, e.g.


  let x = x + 1

simply loops.  I would like to be in the position to tell Haskell what I 
mean, whether I want recursion or not.



I've gone to some trouble to dig up an nhc98 install (but can't seem to
find one among my computers and GHC 7 won't build the source thanks to
library re-orgs etc.)  Because, I vaguely recall that nhc98's rules
were different here?  Anyone in a position to prove me wrong?


I would doubt that nhc98 would interpret  let xs = 0 : xs  differently 
than ghc if it implemented anything close to the Haskell 98 standard. 
But I am not in a position to prove you wrong.


Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-recursive let [Was: GHC bug? Let with guards loops]

2013-07-10 Thread Andreas Abel

On 10.07.13 11:42 AM, Ertugrul Söylemez wrote:

I think we are all aware that shadowing is
a bad idea, no matter whether you do it through Identity or
non-recursive let.


WHAT??

[This is Richard Bird's WHAT?? when someone said that using folds is 
like programming in assembly language.]


How can you think this if we say we WANT shadowing?!


Also if you are serious about this, you would have to make non-recursive
let the default to get OCaml-style behavior, which would be an extremely
invasive change.  We would have to fix pretty much all packages, all
tutorials, all books, all wiki pages, etc.  Otherwise just like you may
forget to renumber your variables, you may just as well forget to add
the norec keyword or whatever the syntax would be.


Wow, this is getting really dramatic now.  Don't be afraid, now one will 
force you to shadow any of your identifiers...


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] GHC bug? Let with guards loops

2013-07-09 Thread Andreas Abel

Hi, is this a known bug or feature of GHC (7.4.1, 7.6.3)?:

I got a looping behavior in one of my programs and could not explain 
why.  When I rewrote an irrefutable let with guards to use a case 
instead, the loop disappeared.  Cut-down:


  works = case Just 1 of { Just x | x  0 - x }

  loops = let Just x | x  0 = Just 1 in x

works returns 1, loops loops.  If x is unused on the rhs, the 
non-termination disappears.


  works' = let Just x | x  0 = Just 1 in 42

Is this intended by the Haskell semantics or is this a bug?  I would 
have assumed that non-recursive let and single-branch case are 
interchangeable, but apparently, not...


Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] GHC bug? Let with guards loops

2013-07-09 Thread Andreas Abel
Thanks, Dan and Roman, for the explanation.  So I have to delete the 
explanation non-recursive let = single-branch case from my brain.


I thought the guards in a let are assertations, but in fact it is more 
like an if.  Ok.


But then I do not see why the pattern variables are in scope in the 
guards in


  let p | g = e

The variables in p are only bound to their values (given by e) if the 
guard g evaluates to True.  But how can g evaluate if it has yet unbound 
variables?  How can ever a pattern variable of p be *needed* to compute 
the value of the guard?  My conjecture is that it cannot, so it does not 
make sense to consider variables of g bound by p.  Maybe you can cook up 
some counterexample.


I think the pattern variables of p should not be in scope in g, and 
shadowing free variables of g by pattern variables of p should be forbidden.


Cheers,
Andreas

On 09.07.2013 17:05, Dan Doel wrote: The definition

  Just x | x  0 = Just 1

 is recursive. It conditionally defines Just x as Just 1 when x  0 (and
 as bottom otherwise). So it must know the result before it can test the
 guard, but it cannot know the result until the guard is tested. Consider
 an augmented definition:

  Just x | x  0  = Just 1
 | x = 0 = Just 0

 What is x?

On 09.07.2013 17:49, Roman Cheplyaka wrote:

As Dan said, this behaviour is correct.

The confusing thing here is that in case expressions guards are attached
to the patterns (i.e. to the lhs), while in let expressions they are
attached to the rhs.

So, despite the common Just x | x  0 part, your examples mean rather
different things.

Here's the translation of 'loops' according to the Report:

   loops =
 let Just x =
   case () of
 () | x  0 - Just 1
 in x

Here it's obvious that 'x' is used in the rhs of its own definition.

Roman

* Andreas Abel andreas.a...@ifi.lmu.de [2013-07-09 16:42:00+0200]

Hi, is this a known bug or feature of GHC (7.4.1, 7.6.3)?:

I got a looping behavior in one of my programs and could not explain
why.  When I rewrote an irrefutable let with guards to use a case
instead, the loop disappeared.  Cut-down:

   works = case Just 1 of { Just x | x  0 - x }

   loops = let Just x | x  0 = Just 1 in x

works returns 1, loops loops.  If x is unused on the rhs, the
non-termination disappears.

   works' = let Just x | x  0 = Just 1 in 42

Is this intended by the Haskell semantics or is this a bug?  I would
have assumed that non-recursive let and single-branch case are
interchangeable, but apparently, not...

Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe





--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] GHC bug? Let with guards loops

2013-07-09 Thread Andreas Abel

Hi Felipe,  thanks for the centavos.

So you mean that in

  let p | g = e where bs
  in ...

the bindings bs should be in scope in g (and of course the variables of 
p are in scope in bs).  Mmh, the bindings in bs that do not uses the 
pattern variables could be useful in g, but the other bindings will 
still lead to non-termination.  Maybe such an analysis is too 
sophisticated.  My lesson is to use case instead of let.  Only that the 
let syntax is nicer and indentation-friendlier than case, so it would be 
preferable.


The greater evil is that Haskell does not have a non-recursive let. 
This is source of many non-termination bugs, including this one here. 
let should be non-recursive by default, and for recursion we could have 
the good old let rec.


Cheers,
Andreas

On 09.07.2013 19:23, Felipe Almeida Lessa wrote:

Well, you could use p's type for something.

   let x | foo (undefined `asTypeOf` x) = 3
   foo _ = True
   in x

Arguably not very useful.  It seems to me that the most compelling
rationale is being consistent with the cases where, instead of being a
data type, p is a function.  Even so most of the time you won't be
recursing on the guard.  But, since you could use something from the
where clause on the guard, and we certainly won't be restricting
recursing on the where clause, it also seems compelling to allow
recursion on the guard.

My 2 centavos, =)


On Tue, Jul 9, 2013 at 2:12 PM, Andreas Abel andreas.a...@ifi.lmu.de wrote:

Thanks, Dan and Roman, for the explanation.  So I have to delete the
explanation non-recursive let = single-branch case from my brain.

I thought the guards in a let are assertations, but in fact it is more like
an if.  Ok.

But then I do not see why the pattern variables are in scope in the guards
in

   let p | g = e

The variables in p are only bound to their values (given by e) if the guard
g evaluates to True.  But how can g evaluate if it has yet unbound
variables?  How can ever a pattern variable of p be *needed* to compute the
value of the guard?  My conjecture is that it cannot, so it does not make
sense to consider variables of g bound by p.  Maybe you can cook up some
counterexample.

I think the pattern variables of p should not be in scope in g, and
shadowing free variables of g by pattern variables of p should be forbidden.

Cheers,
Andreas

On 09.07.2013 17:05, Dan Doel wrote: The definition



  Just x | x  0 = Just 1

is recursive. It conditionally defines Just x as Just 1 when x  0 (and
as bottom otherwise). So it must know the result before it can test the
guard, but it cannot know the result until the guard is tested. Consider
an augmented definition:

  Just x | x  0  = Just 1
 | x = 0 = Just 0

What is x?


On 09.07.2013 17:49, Roman Cheplyaka wrote:


As Dan said, this behaviour is correct.

The confusing thing here is that in case expressions guards are attached
to the patterns (i.e. to the lhs), while in let expressions they are
attached to the rhs.

So, despite the common Just x | x  0 part, your examples mean rather
different things.

Here's the translation of 'loops' according to the Report:

loops =
  let Just x =
case () of
  () | x  0 - Just 1
  in x

Here it's obvious that 'x' is used in the rhs of its own definition.

Roman

* Andreas Abel andreas.a...@ifi.lmu.de [2013-07-09 16:42:00+0200]


Hi, is this a known bug or feature of GHC (7.4.1, 7.6.3)?:

I got a looping behavior in one of my programs and could not explain
why.  When I rewrote an irrefutable let with guards to use a case
instead, the loop disappeared.  Cut-down:

works = case Just 1 of { Just x | x  0 - x }

loops = let Just x | x  0 = Just 1 in x

works returns 1, loops loops.  If x is unused on the rhs, the
non-termination disappears.

works' = let Just x | x  0 = Just 1 in 42

Is this intended by the Haskell semantics or is this a bug?  I would
have assumed that non-recursive let and single-branch case are
interchangeable, but apparently, not...




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] GHC bug? Let with guards loops

2013-07-09 Thread Andreas Abel

On 09.07.2013 19:56, Dan Doel wrote:

With pattern guards, it's difficult to say whether it is never 'useful'
to have things like the following work:

 C x | C' y z - f x = ...

But I'd also shy away from changing the behavior because it causes a lot
of consistency issues. In

 let
   f vs1 | gs1 = es1
   h vs2 | gs2 = es2
   ...

we have that f and h are in scope in both gs1 and gs2. Does it make
sense to call f in gs1? It's easy to loop if you do. So should f not be
in scope in gs1, but h is, and vice versa for gs2? But they're both in
scope for es1 and es2?


If f and h are really mutually recursive, then they should not be in 
scope in gs1 and gs2.


If the first thing you do in the body of f is calling f (which happens 
if f appears in gs1), then you are bound to loop.  But of course, if vs 
are not just variables but patterns, then the first thing you do is 
matching, so using f in gs1 could be fine.


I am getting on muddy grounds here, better retreat.  I was thinking only 
of non-recursive let.

In the report


http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-440003.12

it says that

  let p = e1  in  e0=   case e1 of ~p - e0
where no variable in p appears free in e1

but this applies only for patterns p without guards, and I would have 
expected to be true also for patterns with guards.



And if we leave the above alone, then what about the case where there
are no vs? Is that different? Or is it only left-hand patterns that
get this treatment?


Yes, it is only about the things defined by the let binding (in this 
case, f and g).  The variables in vs1 are bound by calling f, but by f's 
body.



Also, it might have some weird consequences for moving code around. Like:

 let Just x | x  0 = Just 1


Non-recursive.


 let Just x | y  0 = Just 1
 y = x


Recursive.


 let Just x | b = Just 1
   where b = x  0


Recursive?


 let Just x | b = Just 1
 b = x  0


Recursive. (Like 2.)


These all behave the same way now. Which ones should change?


Only the first one?  Hard to tell.


If Haskell had a non-recursive let, that'd probably be a different
story. But it doesn't.


Definitely agree.


On Tue, Jul 9, 2013 at 1:12 PM, Andreas Abel andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.de wrote:

Thanks, Dan and Roman, for the explanation.  So I have to delete the
explanation non-recursive let = single-branch case from my brain.

I thought the guards in a let are assertations, but in fact it is
more like an if.  Ok.

But then I do not see why the pattern variables are in scope in the
guards in

   let p | g = e

The variables in p are only bound to their values (given by e) if
the guard g evaluates to True.  But how can g evaluate if it has yet
unbound variables?  How can ever a pattern variable of p be *needed*
to compute the value of the guard?  My conjecture is that it cannot,
so it does not make sense to consider variables of g bound by p.
  Maybe you can cook up some counterexample.

I think the pattern variables of p should not be in scope in g, and
shadowing free variables of g by pattern variables of p should be
forbidden.

Cheers,
Andreas

On 09.07.2013 17:05, Dan Doel wrote: The definition

 
   Just x | x  0 = Just 1
 
  is recursive. It conditionally defines Just x as Just 1 when x 
0 (and
  as bottom otherwise). So it must know the result before it can
test the
  guard, but it cannot know the result until the guard is tested.
Consider
  an augmented definition:
 
   Just x | x  0  = Just 1
  | x = 0 = Just 0
 
  What is x?

On 09.07.2013 17:49, Roman Cheplyaka wrote:

As Dan said, this behaviour is correct.

The confusing thing here is that in case expressions guards are
attached
to the patterns (i.e. to the lhs), while in let expressions they are
attached to the rhs.

So, despite the common Just x | x  0 part, your examples mean
rather
different things.

Here's the translation of 'loops' according to the Report:

loops =
  let Just x =
case () of
  () | x  0 - Just 1
  in x

Here it's obvious that 'x' is used in the rhs of its own definition.

Roman

* Andreas Abel andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.de [2013-07-09 16:42:00+0200]

Hi, is this a known bug or feature of GHC (7.4.1, 7.6.3)?:

I got a looping behavior in one of my programs and could not
explain
why.  When I rewrote an irrefutable let with guards to use a
case
instead, the loop disappeared.  Cut-down:

works = case Just 1 of { Just x | x  0 - x }

loops = let Just x | x  0

Re: [Haskell-cafe] mapFst and mapSnd

2013-05-28 Thread Andreas Abel

See Agda.Utils.Tuple :-)

-- | Bifunctoriality for pairs.
(-*-) :: (a - c) - (b - d) - (a,b) - (c,d)
(f -*- g) ~(x,y) = (f x, g y)

-- | @mapFst f = f -*- id@
mapFst :: (a - c) - (a,b) - (c,b)
mapFst f ~(x,y) = (f x, y)

-- | @mapSnd g = id -*- g@
mapSnd :: (b - d) - (a,b) - (a,d)
mapSnd g ~(x,y) = (x, g y)

I think mapPair, mapFst, and mapSnd are canonical names that could be 
added to Data.Tuple.  But if you suggest this on librar...@haskell.org, 
you get probably turned down, see e.g.


  http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17411

Cheers,
Andreas

On 28.05.2013 15:34, Petr Pudlák wrote:

Dne 28.5.2013 10:54, Dominique Devriese napsal(a):

Hi all,

I often find myself needing the following definitions:

   mapPair :: (a - b) - (c - d) - (a,c) - (b,d)
   mapPair f g (x,y) = (f x, g y)

   mapFst :: (a - b) - (a,c) - (b,c)
   mapFst f = mapPair f id

   mapSnd :: (b - c) - (a,b) - (a,c)
   mapSnd = mapPair id

But they seem missing from the prelude and Hoogle or Hayoo only turn
up versions of them in packages like scion or fgl.  Has anyone else
felt the need for these functions?  Am I missing some generalisation
of them perhaps?

Apart from Arrows, there is also package bifunctors that defines this
functionality for (,), Either and a few others:
http://hackage.haskell.org/packages/archive/bifunctors/3.2.0.1/doc/html/Data-Bifunctor.html


Petr Pudlak


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Lambda Calculus question on equivalence

2013-05-03 Thread Andreas Abel
The answer to your question is given in Boehm's theorem, and the answer 
is no, as you suspect.


For the untyped lambda-calculus, alpha-equivalence of beta-eta normal 
forms is the same as observational equivalence.  Or put the other way 
round, two normal forms which are not alpha-equivalent can be separated 
by an observation L.


Cheers,
Andreas

On 03.05.2013 00:33, Roman Cheplyaka wrote:

IIRC, Barendregt'84 monography (The Lambda Calculus: Its Syntax and
Semantics) has a significant part of it devoted to this question.

* Ian Price ianpric...@googlemail.com [2013-05-02 20:47:07+0100]

Hi,

I know this isn't perhaps the best forum for this, but maybe you can
give me some pointers.

Earlier today I was thinking about De Bruijn Indices, and they have the
property that two lambda terms that are alpha-equivalent, are expressed
in the same way, and I got to wondering if it was possible to find a
useful notion of function equality, such that it would be equivalent to
structural equality (aside from just defining it this way), though
obviously we cannot do this in general.

So the question I came up with was:

Can two normalised (i.e. no subterm can be beta or eta reduced) lambda
terms be observationally equivalent, but not alpha equivalent?

By observationally equivalent, I mean A and B are observationally
equivalent if for all lambda terms L: (L A) is equivalent to (L B) and
(A L) is equivalent to (B L). The definition is admittedly circular, but
I hope it conveys enough to understand what I'm after.

My intuition is no, but I am not sure how to prove it, and it seems to
me this sort of question has likely been answered before.

Cheers
--
Ian Price -- shift-reset.com

Programming is like pinball. The reward for doing it well is
the opportunity to do it again - from The Wizardy Compiled


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Conflicting bindings legal?!

2013-02-27 Thread Andreas Abel

Hi Tillmann,

no, I am not against shadowing.  It's a two-edged sword, but I find it 
very useful.


Shadowing is very intuitive if one can proceed in a left-to-right, 
top-to-bottom order, just as one reads.  Then it is clear that the later 
occurrence of a binding shadows the earlier one.  No formal spec. is 
needed to resolve binding in that case.


The confusion comes when one binding comes from a 'where' which is below 
the use, and another comes from a 'do' or 'let' which is above the use. 
 Then there is no trivial intuitive reading (especially if the block 
structure is implicit and handled by indentation).


Cheers,
Andreas

On 26.02.2013 10:57, Tillmann Rendel wrote:

Hi,

Andreas Abel wrote:

To your amusement, I found the following in the Agda source:

abstractToConcreteCtx :: ToConcrete a c = Precedence - a - TCM c
abstractToConcreteCtx ctx x = do
   scope - getScope
   let scope' = scope { scopePrecedence = ctx }
   return $ abstractToConcrete (makeEnv scope') x
   where
 scope = (currentScope defaultEnv) { scopePrecedence = ctx }

I am surprised this is a legal form of shadowing.  To understand which
definition of 'scope' shadows the other, I have to consult the formal
definition of Haskell.


Isn't this just an instance of the following, more general rule:

To understand what a piece of code means, I have to consult the formal
definition of the language the code is written in.


In the case you cite, you just have to desugar the do notation


abstractToConcreteCtx :: ToConcrete a c = Precedence - a - TCM c
abstractToConcreteCtx ctx x =
 getScope = (\scope -
 let scope' = scope { scopePrecedence = ctx } in
 return $ abstractToConcrete (makeEnv scope') x)
   where
 scope = (currentScope defaultEnv) { scopePrecedence = ctx }


and it becomes clear by the nesting structure that the lambda-binding
shadows the where-binding. It seems that if you argue against this case,
you argue against shadowing in general. Should we adopt the Barendregt
convention as a style guide for programming?

   Tillmann




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Conflicting bindings legal?!

2013-02-26 Thread Andreas Abel

To your amusement, I found the following in the Agda source:

abstractToConcreteCtx :: ToConcrete a c = Precedence - a - TCM c
abstractToConcreteCtx ctx x = do
  scope - getScope
  let scope' = scope { scopePrecedence = ctx }
  return $ abstractToConcrete (makeEnv scope') x
  where
scope = (currentScope defaultEnv) { scopePrecedence = ctx }

I am surprised this is a legal form of shadowing.  To understand which 
definition of 'scope' shadows the other, I have to consult the formal 
definition of Haskell.


But I studied computer science to *not* become a lawyer!!


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Conflicting bindings legal?!

2013-02-26 Thread Andreas Abel
Luckily, {-# OPTIONS -fwarn-unused-binds #-} saves me from searching for 
the formal spec...


On 26.02.13 10:25 AM, Andreas Abel wrote:

To your amusement, I found the following in the Agda source:

abstractToConcreteCtx :: ToConcrete a c = Precedence - a - TCM c
abstractToConcreteCtx ctx x = do
   scope - getScope
   let scope' = scope { scopePrecedence = ctx }
   return $ abstractToConcrete (makeEnv scope') x
   where
 scope = (currentScope defaultEnv) { scopePrecedence = ctx }

I am surprised this is a legal form of shadowing.  To understand which
definition of 'scope' shadows the other, I have to consult the formal
definition of Haskell.

But I studied computer science to *not* become a lawyer!!


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] mtl: Why there is Monoid w constraint in the definition of class MonadWriter?

2012-12-10 Thread Andreas Abel
 return = MyWriter 0
 MyWriter n x = k =
   let MyWriter n' y = k x
   in MyWriter (n+n') y

   instance MonadWriter Integer MyWriter where
 tell n = MyWriter n ()
 listen (MyWriter n x) = return (x,n)
 pass (MyWriter n (a,f)) = MyWriter (f n) a

Yes, integers do form a monoid when equipped with 0 and (+). However, we
know well why they are not an instance of Monoid — namely, there's more
than one way they form a monoid.

Even if something is in theory a monoid, there may be technical reasons
not to declare it a Monoid. Likewise, imposing a (technical) superclass
constraint on MonadWriter has nothing to do with whether the Monad will
be well-behaved.

This is true in both directions: even if the type is an instance of
Monoid, nothing forces the Monad instance to use the Monoid instance.
I.e. I can declare a MonadWriter on the Sum newtype whose bind, instead
of adding, subtracts the numbers.

Roman


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] lambda case

2012-11-30 Thread Andreas Abel

Right, case..of is superfluous,

  case e of
branches

can now be written as

  e | \case
branches

with backwards application | (or some prefer  --- sadly, the proposal 
to add backwards appliation to base did not make it to a consensus).


This is in accordance to the monadic

  me = \case
branches

If there was an opportunity to make drastic language changes, case..of 
could be disposed of altogether.  \case could become 'cases' or 'match' 
or 'fun' (rather not 'of', for my taste).


The current compromise it not too bad, I think.

Unfortunately, I have to wait for 7.6 to become the standard before 
using \case in Agda source...


Cheers,
Andreas

On 30.11.12 7:25 AM, Herbert Valerio Riedel wrote:

Jon Fairbairn jon.fairba...@cl.cam.ac.uk writes:

[...]


“\case” complicates lambda, using “of” simply breaks “case … of …”
into two easily understood parts.


Just some observation (I'm rather late to the lambda-case discussion, so
this might have been already pointed out previously):

if the reserved keyword 'of' was to take the place of '\case', shouldn't
then

   'case' exp

w/o the 'of' { alts }-part become a separately valid expression (with
'case' essentially meaning 'flip ($)') to really break it up into two
independent parts? Then 'case exp of { alts }' wouldn't be a special
form anymore, but would just result from combining 'case' and 'of';

'case' wouldn't even need to be a reserved keyword (and thus the grammar
could be simplified), if it wasn't for the current grammar which
requires to isolate a \case-expression by using () or $, consider e.g.:

   {-# LANGUAGE LambdaCase #-}

   import System.Environment

   case' :: b - (b - c) - c
   case' = flip ($)

   main = do
 s - getArgs

 case' s $ \case  -- image '\case' was actually '\of' or 'of'
   [x] - putStrLn (Hello  ++ x)
   _   - putStrLn wrong number of arguments given


just my 2¢

cheers,
   hvr

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Is anyone working on a sparse matrix library in Haskell?

2012-11-29 Thread Andreas Abel

Hi Mark,

I might become your user.  Currently, for Agda I have rolled my own 
sparse matrix implementation, see


http://hackage.haskell.org/packages/archive/Agda/latest/doc/html/src/Agda-Termination-SparseMatrix.html

Cheers,
Andreas

On 29.11.12 5:03 PM, Mark Flamer wrote:

I am looking to continue to learn Haskell while working on something that
might eventually be useful to others and get posted on Hackage. I have
written quite a bit of Haskell code now, some useful and a lot just throw
away for learning. In the past others have expressed interest in having a
native Haskell sparse matrix and linear algebra library available(not just
bindings to a C lib). This in combination with FEM is one of my interests.
So my questions, is anyone currently working on a project like this? Does it
seem like a good project/addition to the community? I'm also interested if
anyone has any other project idea's, maybe even to collaborate on. Thanks



--
View this message in context: 
http://haskell.1045720.n5.nabble.com/Is-anyone-working-on-a-sparse-matrix-library-in-Haskell-tp5721452.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] lambda case (was Re: A big hurray for lambda-case (and all the other good stuff))

2012-11-29 Thread Andreas Abel
I had been missing a pattern matching lambda in Haskell for a long time 
(SML had fn since ages) and my typical use will be


  monadic_expr = \case
branches

I think \case is not the worst choice, certainly better than of ...

Thanks to the GHC 7.6 developers!

Cheers,
Andreas

On 29.11.12 12:49 PM, Jon Fairbairn wrote:

Ben Franksen ben.frank...@online.de writes:


just wanted to drop by to say how much I like the new lambda case extension.
I use it all the time and I just *love* how it relieves me from conjuring up
dummy variables, which makes teh code not only esier to write but also to
read.



[…] should *definitely* go into Haskell'13.


As I was opposed to the suggestion for lambda case I didn’t
really follow the discussion of the syntax, but I’m puzzled by
the choice. To me it seems obvious that if we are going to do
this (as opposed to something more decomposable like
lambda-match), we should do it simply by making the “case exp”
part of a case expression optional. So the syntax for lambda-
case would be

of {alts…}

and we would then describe

case e of {…}

as syntactic sugar for

(of {…}) (e)

Doing it this way doesn’t introduce any new syntactic elements
and has fewer tokens at the point of use.

I don’t see any need for a \ in the syntax: this is a functional
language we are talking about after all. Once we know that “of”
introduces a function, that should be enough.



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Taking over ghc-core

2012-11-14 Thread Andreas Abel

Excellent!

With ghc-core being maintained again, we can start thinking about 
compiling Agda to core instead of hs.


Andreas

On 11.11.12 11:41 AM, Bas van Dijk wrote:

Great!

On 10 November 2012 16:17, Shachaf Ben-Kiki shac...@gmail.com wrote:

With Don Stewart's blessing
(https://twitter.com/donsbot/status/267060717843279872), I'll be
taking over maintainership of ghc-core, which hasn't been updated
since 2010. I'll release a version with support for GHC 7.6 later
today.

 Shachaf


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] mtl-2.1 severly broken, cabal needs blacklisting

2012-11-13 Thread Andreas Abel
After 2 days of shrinking 251 modules of source code to a few lines I 
realized that modify in MonadState causes loop in mtl-2.1.



http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#modify

The bug has been fixed, apparently seven month ago.

  https://github.com/ekmett/mtl/pull/1

However, the malicious mtl-2.1 still lingers on: it is available from 
hackage and installed in many systems.


This calls for a means of blacklisting broken or malicious packages.

  cabal update

should also pull a blacklist of packages that will never be selected by 
cabal install (except maybe by explicit user safety overriding).


I think such a mechanism is not only necessary for security purposes, 
but also to safe the valuable resources of our community.


Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] mtl-2.1 severly broken, cabal needs blacklisting

2012-11-13 Thread Andreas Abel

On 13.11.2012 17:39, Dan Burton wrote:

Mixed feelings here. I personally subscribe to the philosophy of do one
thing and do it well; perhaps this sort of functionality would be
better delegated to a new curation tool such as the one described in
Michael Snoyman's recent blog post.
http://www.yesodweb.com/blog/2012/11/solving-cabal-hell


I think Michael Snoyman's approach goes farther than mine and solves a 
slightly different problem.  I am not concerned with the dependency 
hell but with a means of safely avoiding bugged packages.


Uploading a bugged package can happen to anyone of us, but cabal/hackage 
does not provide a suitable means to rectify the situation.  Cabal's 
philosophy currently includes a monotonicity assumption: newer is better 
and more correct.  As a consequence, packages do not get removed or 
replaced since that could break compilation of other packages depending 
on a special version number of a package.  The calamity is that bugged 
package live on, and cabal install is oblivious of this.


If one could blacklist a certain version of a package, cabal could pick 
the next higher available version, as a sort of redirection mechanism to 
the fixed package.  For instance, if I have issued


  mylib-2.1
  mylib-2.2
  mylib-3.0

and I discover a bug in mylib-2.1, I could blacklist mylib-2.1 and 
upload a bugfix version


  mylib-2.1.1

that would be picked by cabal instead of mylib-2.1.

Those user packages that rely on the specific interface of mylib-2.1 
(e.g. having a constraint mylib == 2.1) and do not work with mylib-2.2 
would still work, since they would be built with mylib-2.1.1



On Tue, Nov 13, 2012 at 9:27 AM, Andreas Abel andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.de wrote:

After 2 days of shrinking 251 modules of source code to a few lines
I realized that modify in MonadState causes loop in mtl-2.1.



http://hackage.haskell.org/__packages/archive/mtl/2.1/doc/__html/src/Control-Monad-State-__Class.html#modify

http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#modify

The bug has been fixed, apparently seven month ago.

https://github.com/ekmett/mtl/__pull/1
https://github.com/ekmett/mtl/pull/1

However, the malicious mtl-2.1 still lingers on: it is available
from hackage and installed in many systems.

This calls for a means of blacklisting broken or malicious packages.

   cabal update

should also pull a blacklist of packages that will never be selected
by cabal install (except maybe by explicit user safety overriding).

I think such a mechanism is not only necessary for security
purposes, but also to safe the valuable resources of our community.

Cheers,
Andreas


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] hackageDB haddock errors

2012-11-13 Thread Andreas Abel
I found that for the recently uploaded Agda-2.3.2 there is no 
haddockumentation.  Stumbling over the build protocol by chance



http://hackage.haskell.org/packages/archive/Agda/2.3.2/logs/success/ghc-7.6

I searched for whether haddock had been executed and found, yes, but 
also, it failed:


  ...
  40% (  2 /  5) in 'Agda.Syntax.Abstract.Pretty'

haddock: internal error: /tmp/ghc17357_0/ghc17357_126.s: hPutBuf: 
resource exhausted (No space left on device)


Q: Could this build be run again, with sufficient disk space?


For gtk-0.12.4 there is another explanation: it has build failures:

http://hackage.haskell.org/packages/archive/gtk/0.12.4/logs/failure/ghc-7.6


On 13.11.2012 16:41, timothyho...@seznam.cz wrote:

Hello,
There are several packages without haddock documentation on hackage.
The one that bugs me right now, is the latest version of gtk2hs:
http://hackage.haskell.org/package/gtk
I've been told that this may be due to hackage updating docs with an
infrequent cron job, so that new packages don't get their docs for a
long time.  Whatever is causing it, the fact that hayoo
http://holumbus.fh-wedel.de/hayoo/hayoo.html always uses the most
frequent docs, means that I cannot currently search for anything gtk2hs
related :(

Can someone please look into prodding this cron job so it doesn't take
days to run, or look into resolving any errors that might be causing
this unfortunate behaviour?

Thank you for your time,
and happy hacking,
Timothy




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] mtl-2.1 severly broken, cabal needs blacklisting

2012-11-13 Thread Andreas Abel

On 13.11.12 11:13 PM, Jean-Philippe Bernardy wrote:

Blacklisting equals releasing a bugfix.


Not quite.


Using version number conventions, identifying such a release should be easy.

If there exists a bugfix release for a package currently in use, then
cabal should emit a warning.


Warnings are easily overlooked.  In a typical cabal install session I 
see tons of irrelevant warnings floating by.



On Nov 13, 2012 6:12 PM, Andreas Abel andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.de wrote:

On 13.11.2012 17:39, Dan Burton wrote:

Mixed feelings here. I personally subscribe to the philosophy of
do one
thing and do it well; perhaps this sort of functionality would be
better delegated to a new curation tool such as the one
described in
Michael Snoyman's recent blog post.
http://www.yesodweb.com/blog/__2012/11/solving-cabal-hell
http://www.yesodweb.com/blog/2012/11/solving-cabal-hell


I think Michael Snoyman's approach goes farther than mine and solves
a slightly different problem.  I am not concerned with the
dependency hell but with a means of safely avoiding bugged packages.

Uploading a bugged package can happen to anyone of us, but
cabal/hackage does not provide a suitable means to rectify the
situation.  Cabal's philosophy currently includes a monotonicity
assumption: newer is better and more correct.  As a consequence,
packages do not get removed or replaced since that could break
compilation of other packages depending on a special version number
of a package.  The calamity is that bugged package live on, and
cabal install is oblivious of this.

If one could blacklist a certain version of a package, cabal could
pick the next higher available version, as a sort of redirection
mechanism to the fixed package.  For instance, if I have issued

   mylib-2.1
   mylib-2.2
   mylib-3.0

and I discover a bug in mylib-2.1, I could blacklist mylib-2.1 and
upload a bugfix version

   mylib-2.1.1

that would be picked by cabal instead of mylib-2.1.

Those user packages that rely on the specific interface of mylib-2.1
(e.g. having a constraint mylib == 2.1) and do not work with
mylib-2.2 would still work, since they would be built with mylib-2.1.1

On Tue, Nov 13, 2012 at 9:27 AM, Andreas Abel
andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de
mailto:andreas.a...@ifi.lmu.__de
mailto:andreas.a...@ifi.lmu.de wrote:

 After 2 days of shrinking 251 modules of source code to a
few lines
 I realized that modify in MonadState causes loop in
mtl-2.1.



http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#modify

http://hackage.haskell.org/__packages/archive/mtl/2.1/doc/__html/src/Control-Monad-State-__Class.html#modify


http://hackage.haskell.org/__packages/archive/mtl/2.1/doc/__html/src/Control-Monad-State-__Class.html#modify

http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Monad-State-Class.html#modify

 The bug has been fixed, apparently seven month ago.

https://github.com/ekmett/mtl/pull/1
https://github.com/ekmett/mtl/__pull/1
 https://github.com/ekmett/__mtl/pull/1
https://github.com/ekmett/mtl/pull/1

 However, the malicious mtl-2.1 still lingers on: it is
available
 from hackage and installed in many systems.

 This calls for a means of blacklisting broken or malicious
packages.

cabal update

 should also pull a blacklist of packages that will never be
selected
 by cabal install (except maybe by explicit user safety
overriding).

 I think such a mechanism is not only necessary for security
 purposes, but also to safe the valuable resources of our
community.

 Cheers,
 Andreas


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de mailto:andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~__abel/ http://www2.tcs.ifi.lmu.de/~abel/

_
Libraries mailing list
librar...@haskell.org mailto:librar...@haskell.org
http://www.haskell.org/__mailman/listinfo/libraries
http://www.haskell.org/mailman/listinfo/libraries



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman

Re: [Haskell-cafe] more sharing in generated code

2012-11-03 Thread Andreas Abel

On 03.11.12 10:05 AM, Peter Divianszky wrote:

Suppose we have a record update

   r { x = f (r x)}

and suppose that most of the time f returns it's argument unchanged.

Recently I've heard about Q-combinators.
Central idea: Change (f :: a - a) to (f' :: a - Maybe a) returning
Nothing when the value didn't change.
Then we can replace the record update with smarter code which
preserves more sharing.


Just adding a remark here:  I actually played with these Q-combinators, 
they actually worsened performance of Agda.  The problem is that they 
make the code strict.  The performance loss due to strictness 
outweighted the potential performance gain by increased sharing. 
Q-combinators were developed by John Harrison in the context of ML, 
which is strict anyway.


I guess a compiler support for smart record update would not have the 
strictness penalty.


Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] [Agda] How to avoid T3 fonts in pdf generated with lhs2TeX?

2012-11-02 Thread Andreas Abel

Hi,

I found the problem, it solved itself with an update of the TeXLive suite...

  https://github.com/kosmikus/lhs2tex/issues/24

Thanks for your help!
Andreas

On 01.11.12 11:15 PM, Dominique Devriese wrote:

Andreas,

2012/11/1 Andreas Abel andreas.a...@ifi.lmu.de:

Hello,

maybe someone has experience in publishing papers that use lhs2TeX and
unicode characters with ACM, and has been in my situation before...

Sheridan, who publishes for ACM, does not like T3 fonts. However, lhs2tex
--agda does make use of T3 fonts via:

   \RequirePackage[utf8x]{inputenc}

If I remove this, my unicode characters are garbled in the lhs2tex-generated
code. Does anoyone know a smart workaround besides replacing all the unicode
characters manually by some math symbols in the .tex file?


Not sure about all this, but perhaps you can try to use utf8 instead
of utf8x and manually define translations for the unicode characters
that you use,e.g.:

\DeclareUnicodeCharacter{2032}{'}
\DeclareUnicodeCharacter{2080}{_0}
\DeclareUnicodeCharacter{2081}{_1}
\DeclareUnicodeCharacter{2082}{_2}
\DeclareUnicodeCharacter{2115}{\mathbb{N}}
\DeclareUnicodeCharacter{2192}{\to}
\DeclareUnicodeCharacter{2200}{\forall\,}

Perhaps you can then somehow avoid translations that use T3 fonts (not
sure what these are though). Note: the numbers are the characters'
unicode hexadecimal representation (AFAIU), which you can find e.g.
using emacs's describe-char.

Dominique

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] How to avoid T3 fonts in pdf generated with lhs2TeX?

2012-11-01 Thread Andreas Abel

Hello,

maybe someone has experience in publishing papers that use lhs2TeX and 
unicode characters with ACM, and has been in my situation before...


Sheridan, who publishes for ACM, does not like T3 fonts. However, 
lhs2tex --agda does make use of T3 fonts via:


  \RequirePackage[utf8x]{inputenc}

If I remove this, my unicode characters are garbled in the 
lhs2tex-generated code. Does anoyone know a smart workaround besides 
replacing all the unicode characters manually by some math symbols in 
the .tex file?


Cheers,
Andreas

--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Why Kleisli composition is not in the Monad signature?

2012-10-22 Thread Andreas Abel
When I teach my students Haskell's monads, I never put Kleisli into my 
mouth.  I tell them that monads are for sequencing effects; and the 
sequencing is visible clearly in


  ()  :: IO a - IO b - IO b
  (=) :: IO a - (a - IO b) - IO b

but not in

  fmap :: (a - b) - IO a - IO b
  join :: IO (IO a) - IO a

To me,

  print 1  print 2

looks natural, and

  print 1 = const (print 2)

still understandable, but

  join $ fmap (const (print 2)) (print 1)

rather not (I needed ghci to get this example right).

I would not want to introduce category theory or Kleisli composition 
just to teach my students some effectful Haskell programming.


Cheers,
Andreas

On 16.10.2012 21:45, Simon Thompson wrote:


Not sure I really have anything substantial to contribute, but it's certainly 
true that if you see

   a - m b

as a generalisation of the usual function type, a - b, then return generalises 
the identity and
kleisli generalises function composition. This makes the types pretty memorable 
(and often the
definitions too).

Simon


On 16 Oct 2012, at 20:14, David Thomas davidleotho...@gmail.com wrote:


class Monad m where
  return :: a - m a
  kleisli :: (a - m b) - (b - m c) - (a - m c)


Simon Thompson | Professor of Logic and Computation
School of Computing | University of Kent | Canterbury, CT2 7NF, UK
s.j.thomp...@kent.ac.uk | M +44 7986 085754 | W www.cs.kent.ac.uk/~sjt


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Over general types are too easy to make.

2012-09-04 Thread Andreas Abel
 list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Haskell's type inference considered harmful

2012-07-23 Thread Andreas Abel
Thanks for your answer and your examples.  It would be worthwile 
collecting such examples in a small article.


I think some of the problems with type inference come from insufficient 
theory about metavariables.  When I started studying higher-order 
unification I always wondered what the scope of a metavariable is.  It 
is created at some point and then just sits there waiting to be solved 
by a constraint.  However, it is not clear where these constraints may 
come from and at what time a metavariable should be declared unsolved or 
be generalized over.


In the HM toy calculus (lambda + let), it is spelled out: 
generalization must happen after a let, such that the solution for a 
metavariable is determined solely by constraints in the *definition* of 
a symbol, not in its *use*.


I'd be grateful for pointers to work that considers metavariable scope 
in some bigger, more realistic calculi.  In Haskell, one thing that goes 
wrong is that all definitions in a module are considered mutually 
recursive by the type inference algorithm.  But in fact, the definitions 
can be stratified by a strongly connected components analysis.  Doing 
such an analysis, and limiting metavariable scope to an SCC, would 
overcome the problem I outlined in my original mail and would result in 
a more principled treatment of metavariables.


That concerned type inference for global definitions.  It is not clear 
we want the same for local definitions.  There, it makes more sense to 
assume that the programmer can overlook what he is doing, and thus one 
could allow flow of information from the use of a symbol to its 
definition.


Do we want information flow from dead code to live code? I'd say no. 
Dead is unfortunately undecidable; but at least one can identify 
unused local definitions, i.e., statically unreachable definitions. 
Your examples seem to suggest you want such information flow, or maybe not?



On 21.07.2012 12:26, o...@okmij.org wrote:

However, if your are using ExtendedDefaultRules then you are likely to
know you are leaving the clean sound world of type inference.


First of all, ExtendedDefaultRules is enabled by default in
GHCi. Second, my example will work without ExtendedDefaultRules, in
pure Haskell98. It is even shorter:

instance Num Char
main = do
  x - return []
  let y = x
  print . fst $ (x, abs $ head x)
  -- let dead = if False then y ==  else True
  return ()
The printed result is either [] or .

Mainly, if the point is to demonstrate the non-compositionality of type
inference and the effect of the dead code, one can give many many
examples, in Haskell98 or even in SML.

Here is a short one (which does not relies on defaulting. It uses
ExistentialQuantification, which I think is in the new standard or is
about to be.).

{-# LANGUAGE ExistentialQuantification #-}

data Foo = forall a. Show a = Foo [a]
main = do
  x - return []
 let z = Foo x
  let dead = if False then x ==  else True
 return ()

The code type checks. If you _remove_ the dead code, it won't. As you
can see, the dead can have profound, and beneficial influence on
alive, constraining them. (I guess this example is well-timed for Obon).


Ah, I have never been in Japan at that time.


For another example, take type classes. Haskell98 prohibits overlapping of
instances. Checking for overlapping requires the global analysis of the
whole program and is clearly non-compositional. Whether you may define
instance Num (Int,Int)
depends on whether somebody else, in a library you use indirectly,
has already introduced that instance. Perhaps that library is imported
for a function that has nothing to do with treating a pair of Ints as
a Num -- that is, the instance is a dead code for your
program. Nevertheless, instances are always imported, implicitly.


Yes, that's a known problem.


The non-compositionality of type inference occurs even in SML (or
other language with value restriction). For example,

let x = ref [];;

(* let z = if false then x := [1] else ();; *)

x := [true];;

This code type checks. If we uncomment the dead definition, it
won't. So, the type of x cannot be fully determined from its
definition; we need to know the context of its use -- which is
precisely what seems to upset you about Haskell.


To stirr action, mails on haskell-cafe seem useless.


What made you think that? Your questions weren't well answered? What
other venue would you propose?


Yes, they were.  But for discussion about metavariables maybe something 
like a haskell implementor's forum would be more appropriate.  Yet I am 
only an Agda implementor.


Cheers,
Andreas


--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/

___
Haskell-Cafe mailing list
Haskell-Cafe

Re: [Haskell-cafe] Haskell's type inference considered harmful

2012-07-20 Thread Andreas Abel

Haha, I like this example.

However, if your are using ExtendedDefaultRules then you are likely to 
know you are leaving the clean sound world of type inference.  The 
example of my student works on plain GHC...


The other responses to my message confined to point me to best 
practices to avoid the design bugs of Haskell's type inference. 
However, if I want best practices, I can go to JavaScript.


To stirr action, mails on haskell-cafe seem useless.

I am already biased towards Haskell.  But as an unbiased decision maker, 
I would not consider a language with undead code for my projects...


Cheers,
Andreas


On 17.07.12 10:46 AM, o...@okmij.org wrote:

1. Haskell's type inference is NON-COMPOSITIONAL!


Yes, it is -- and there are many examples of it. Here is an example
which has nothing to do with MonomorphismRestriction or numeric
literals

{-# LANGUAGE  #-}

class C a where
 m :: a - Int

instance C () where
 m _ = 1

instance C Bool where
 m _ = 2

main = do
x - return undefined
let y = x
print . fst $ (m x, show x)
-- let dead = if False then not y else True
return ()

The program prints 1. If you uncomment the (really) dead code, it will
print 2. Why? The dead code doesn't even mention x, and it appears
after the printing! What is the role of show x, which doesn't do anything?

Exercises: what is the significance of the monadic bind to x? Why
can't we replace it with let x = undefined?

[Significant hint, don't look at it]

Such a behavior always occurs when we have HM polymorphism restriction
and some sort of non-parametricity -- coupled with default rules or
overlapping instances or some other ways of resolving overloading. All
these features are essential (type-classes are significant,
defaulting is part of the standard and is being used more and more).




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Haskell's type inference considered harmful [Re: [Haskell] A riddle...]

2012-07-17 Thread Andreas Abel
[Is Haskell-Cafe the right place to discuss DESIGN issues of the Haskell 
language?  This message is not about a concrete problem...]


Congratulations to all that solved the riddle so quickly.  (First answer 
in only 8 Minutes!)  Now to the point of the exercise:  Shocking 
realizations.


  1. Haskell's type inference is NON-COMPOSITIONAL!

In the riddle below, I am defining two things f (rgbliste) and g 
(farbliste).  Even though they are not strongly connected, but g comes 
after f in the definition order, the code of g influences the type of f. 
 THAT'S WRONG! :-(


It gets worse:

  2. DEAD CODE changes a program's result!

Yes indeed.  Dead code (farbliste) in the source cannot be removed 
safely.  And:


  3. Haskell casts 181935629 to Word16 value 7693 WITHOUT WARNING!

Needless to say, these are serious problems for leading-edge strongly 
typed language.  The experts are probably aware of this.  But I awoke 
harshly from a sweet dream.


Issue 3 is quite harmful and reminds me more of C than of a strongly 
typed language.  Fixing this is not trivial.  The problem is that all 
numeric constants have type Num a = a, and of course, type variable a 
can be instantiated to Int Word16 or whatever.  Numeric constants need 
to inhabit subclasses of Num, e.g., Word16, Int and Integer /classes/ to 
make this behavior go away.


Update:  There is nothing wrong with Word16 computing modulo 2^16, but a 
literal like 181935629 should not get type Word16 without warning.  Java 
asks for explicit casts in


   byte i = (byte) 1234876;

but mindlessly also in

   byte i = (byte) 123;

which is not a great solution either.


Issues 1/2 go away with

  {-# LANGUAGE NoMonomorphismRestriction #-}

(thx to Christian who pointed me to this).  I wonder why this is not on 
by default?!  There seems to be an unresolved dispute about this... 
http://hackage.haskell.org/trac/haskell-prime/wiki/NoMonomorphismRestriction


But even with MonomorphismRestriction, issue 1/2 are avoidable with a 
more refined approach to type meta variables in the Haskell type 
inference:  After type-checking a strongly connected component, type 
meta variables created for this part of the Haskell program should not 
be instantiated in the (topologically) later defined parts of the 
program.  YOU DON'T WANT THE USE OF A FUNCTION INFLUENCE ITS DEFINITION! 
 There are two alternatives what to do with remaining meta-variables of 
a SCC:


  1. With monomorphism restriction: instantiate to the best type.
 In our example below, Haskell chooses Integer.

  2. Without monomorphism restriction: generalize.

Choice 1 will give an error in the program below, but i rather have an 
error than a silent change of behavior of my program!


Cheers,
Andreas

P.S.: In Agda, in the situation of unsolved metas in an SCC (a mutual 
block), these metas are just frozen, triggering typing errors later 
(since Agda cannot generalize).  The user has to go back an insert more 
type annotations.  But this is safe, whereas silent late instantiation 
breaks compositionality.




On 16.07.2012 17:25, Andreas Abel wrote:

Today a student came to me with a piece of code that worked it executed
by itself, but produced different result in the context of his larger
problem.  We cut down the example to the following:


import Graphics.UI.Gtk

-- should produce [(26471,0,65535),...
rgbliste =
 (map (\ i -
  let rb = 5 * (mod (mod 181935629 (4534+i)) 100)-250+128 in
  let gb = 5 * (mod (mod 128872693 (5148+i)) 100)-250+128 in
  let bb = 5 * (mod (mod 140302469 (7578+i)) 100)-250+128 in
  let r = min 255 $ max 0 rb in
  let g = min 255 $ max 0 gb in
  let b = min 255 $ max 0 bb in
  (r*257,g*257,b*257)) [0..])

--farbliste = map (\ (r,g,b) - Color r g b) rgbliste

main :: IO ()
main = do
  print $ head rgbliste


If you run it, it prints (26471,0,65535).
If you uncomment the def. of farbliste, it prints (44461,65535,65535).

I was surprised.  What is going on?

Cheers,
Andreas




--
Andreas AbelDu bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.a...@ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/




___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe