confusing type error

2014-12-04 Thread Evan Laforge
I recently got a confusing error msg, and reduced it to a small case:

f1 :: Monad m = m Bool
f1 = f2 0 0 'a'

f2 :: Monad m = Int - Float - m Bool
f2 = undefined

From this, it's clear that f2 is being given an extra Char argument it
didn't ask for.  However, the error msg (ghc 7.8.3) is:

Couldn't match type ‘m Bool’ with ‘Bool’
Expected type: Char - m Bool
  Actual type: Char - Bool
Relevant bindings include f1 :: m Bool (bound at Bug.hs:4:1)
The function ‘f2’ is applied to three arguments,
but its type ‘Int - Float - Char - Bool’ has only three
In the expression: f2 0 0 'a'
In an equation for ‘f1’: f1 = f2 0 0 'a'

The confusing part is that 'f2' was applied to three arguments, but
it's type has only three.  It includes the Char in expected and actual
types, and implies that the type of 'f2' includes the Char.  So I took
quite a while to realize that the type of 'f2' in fact *didn't* expect
a Char (and had an 'm'), so that the but its type is *not* in fact
its declared type.

I suppose it infers a type for 'f2' based on its use, and that then
becomes the actual type, but it seems less confusing if it picked
the declared type of 'f2' as its actual type.  Perhaps this is working
as intended, but it it is confusing!  Especially the part about
expected three but got three.

Ideally I'd like to see too many arguments or at least expected
(Char - m Bool) but actually 'm Bool'.  Actually I'd expect the
other way: expected 'm Bool' but got (Char - m Bool)' but I think
ghc has always done it backwards from how I expect.  It looks like
it's substituting (-) for 'm', so maybe it's one of those things
where ((-) a) is also a monad.
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: confusing type error

2014-12-04 Thread Richard Eisenberg
This seems straightforwardly to be a bug, to me. HEAD gives the same behavior 
you report below. Please post on the bug tracker at 
https://ghc.haskell.org/trac/ghc/newticket

Thanks!
Richard

On Dec 4, 2014, at 1:50 PM, Evan Laforge qdun...@gmail.com wrote:

 I recently got a confusing error msg, and reduced it to a small case:
 
 f1 :: Monad m = m Bool
 f1 = f2 0 0 'a'
 
 f2 :: Monad m = Int - Float - m Bool
 f2 = undefined
 
 From this, it's clear that f2 is being given an extra Char argument it
 didn't ask for.  However, the error msg (ghc 7.8.3) is:
 
Couldn't match type ‘m Bool’ with ‘Bool’
Expected type: Char - m Bool
  Actual type: Char - Bool
Relevant bindings include f1 :: m Bool (bound at Bug.hs:4:1)
The function ‘f2’ is applied to three arguments,
but its type ‘Int - Float - Char - Bool’ has only three
In the expression: f2 0 0 'a'
In an equation for ‘f1’: f1 = f2 0 0 'a'
 
 The confusing part is that 'f2' was applied to three arguments, but
 it's type has only three.  It includes the Char in expected and actual
 types, and implies that the type of 'f2' includes the Char.  So I took
 quite a while to realize that the type of 'f2' in fact *didn't* expect
 a Char (and had an 'm'), so that the but its type is *not* in fact
 its declared type.
 
 I suppose it infers a type for 'f2' based on its use, and that then
 becomes the actual type, but it seems less confusing if it picked
 the declared type of 'f2' as its actual type.  Perhaps this is working
 as intended, but it it is confusing!  Especially the part about
 expected three but got three.
 
 Ideally I'd like to see too many arguments or at least expected
 (Char - m Bool) but actually 'm Bool'.  Actually I'd expect the
 other way: expected 'm Bool' but got (Char - m Bool)' but I think
 ghc has always done it backwards from how I expect.  It looks like
 it's substituting (-) for 'm', so maybe it's one of those things
 where ((-) a) is also a monad.
 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
 

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: confusing type error

2014-12-04 Thread Brent Yorgey
Int - Float - Char - Bool  *is* in fact a valid type for f2, since ((-)
Char) is a Monad. However, I agree the error message is confusing,
especially the expected n, but got n part.

-Brent

On Thu, Dec 4, 2014 at 1:50 PM, Evan Laforge qdun...@gmail.com wrote:

 I recently got a confusing error msg, and reduced it to a small case:

 f1 :: Monad m = m Bool
 f1 = f2 0 0 'a'

 f2 :: Monad m = Int - Float - m Bool
 f2 = undefined

 From this, it's clear that f2 is being given an extra Char argument it
 didn't ask for.  However, the error msg (ghc 7.8.3) is:

 Couldn't match type ‘m Bool’ with ‘Bool’
 Expected type: Char - m Bool
   Actual type: Char - Bool
 Relevant bindings include f1 :: m Bool (bound at Bug.hs:4:1)
 The function ‘f2’ is applied to three arguments,
 but its type ‘Int - Float - Char - Bool’ has only three
 In the expression: f2 0 0 'a'
 In an equation for ‘f1’: f1 = f2 0 0 'a'

 The confusing part is that 'f2' was applied to three arguments, but
 it's type has only three.  It includes the Char in expected and actual
 types, and implies that the type of 'f2' includes the Char.  So I took
 quite a while to realize that the type of 'f2' in fact *didn't* expect
 a Char (and had an 'm'), so that the but its type is *not* in fact
 its declared type.

 I suppose it infers a type for 'f2' based on its use, and that then
 becomes the actual type, but it seems less confusing if it picked
 the declared type of 'f2' as its actual type.  Perhaps this is working
 as intended, but it it is confusing!  Especially the part about
 expected three but got three.

 Ideally I'd like to see too many arguments or at least expected
 (Char - m Bool) but actually 'm Bool'.  Actually I'd expect the
 other way: expected 'm Bool' but got (Char - m Bool)' but I think
 ghc has always done it backwards from how I expect.  It looks like
 it's substituting (-) for 'm', so maybe it's one of those things
 where ((-) a) is also a monad.
 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: confusing type error

2014-12-04 Thread migmit
I don't see a bug here. f2 is perfectly OK, so, let's examine f1 more closely.

It tries to get `m Bool` by applying f1 to three arguments: 0, 0, and 'a'. Now, 
since `f2` has the type `Int - Float - n Bool`, where `n` is of kind `* - *` 
(and an instance of `Monad` class, but it's not yet the time to look for 
instances), we have `f2 0 :: Float - n Bool` and `f2 0 0 :: n Bool`. Since 
that is applied to 'a', Haskell deduces that the last type should be something 
like `Char - Something` — or, equivalently, `(-) Char Something`. Therefore, 
it can see that `n` is in fact `(-) Char` and `Something` is `Bool`. 
Therefore, `f2 0 0 'a' :: Bool`. But it is expecting `m Bool`, not `Bool` — 
which is exactly what an error message says.

Отправлено с iPad

 4 дек. 2014 г., в 21:50, Evan Laforge qdun...@gmail.com написал(а):
 
 I recently got a confusing error msg, and reduced it to a small case:
 
 f1 :: Monad m = m Bool
 f1 = f2 0 0 'a'
 
 f2 :: Monad m = Int - Float - m Bool
 f2 = undefined
 
 From this, it's clear that f2 is being given an extra Char argument it
 didn't ask for.  However, the error msg (ghc 7.8.3) is:
 
Couldn't match type ‘m Bool’ with ‘Bool’
Expected type: Char - m Bool
  Actual type: Char - Bool
Relevant bindings include f1 :: m Bool (bound at Bug.hs:4:1)
The function ‘f2’ is applied to three arguments,
but its type ‘Int - Float - Char - Bool’ has only three
In the expression: f2 0 0 'a'
In an equation for ‘f1’: f1 = f2 0 0 'a'
 
 The confusing part is that 'f2' was applied to three arguments, but
 it's type has only three.  It includes the Char in expected and actual
 types, and implies that the type of 'f2' includes the Char.  So I took
 quite a while to realize that the type of 'f2' in fact *didn't* expect
 a Char (and had an 'm'), so that the but its type is *not* in fact
 its declared type.
 
 I suppose it infers a type for 'f2' based on its use, and that then
 becomes the actual type, but it seems less confusing if it picked
 the declared type of 'f2' as its actual type.  Perhaps this is working
 as intended, but it it is confusing!  Especially the part about
 expected three but got three.
 
 Ideally I'd like to see too many arguments or at least expected
 (Char - m Bool) but actually 'm Bool'.  Actually I'd expect the
 other way: expected 'm Bool' but got (Char - m Bool)' but I think
 ghc has always done it backwards from how I expect.  It looks like
 it's substituting (-) for 'm', so maybe it's one of those things
 where ((-) a) is also a monad.
 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: confusing type error

2014-12-04 Thread Yuras Shumovich
It seems to be an instance of
https://ghc.haskell.org/trac/ghc/ticket/7869

But it is fixed (both in HEAD and 7.8). Probably the fix is partial?

On Thu, 2014-12-04 at 14:53 -0500, Richard Eisenberg wrote:
 This seems straightforwardly to be a bug, to me. HEAD gives the same behavior 
 you report below. Please post on the bug tracker at 
 https://ghc.haskell.org/trac/ghc/newticket
 
 Thanks!
 Richard
 
 On Dec 4, 2014, at 1:50 PM, Evan Laforge qdun...@gmail.com wrote:
 
  I recently got a confusing error msg, and reduced it to a small case:
  
  f1 :: Monad m = m Bool
  f1 = f2 0 0 'a'
  
  f2 :: Monad m = Int - Float - m Bool
  f2 = undefined
  
  From this, it's clear that f2 is being given an extra Char argument it
  didn't ask for.  However, the error msg (ghc 7.8.3) is:
  
 Couldn't match type ‘m Bool’ with ‘Bool’
 Expected type: Char - m Bool
   Actual type: Char - Bool
 Relevant bindings include f1 :: m Bool (bound at Bug.hs:4:1)
 The function ‘f2’ is applied to three arguments,
 but its type ‘Int - Float - Char - Bool’ has only three
 In the expression: f2 0 0 'a'
 In an equation for ‘f1’: f1 = f2 0 0 'a'
  
  The confusing part is that 'f2' was applied to three arguments, but
  it's type has only three.  It includes the Char in expected and actual
  types, and implies that the type of 'f2' includes the Char.  So I took
  quite a while to realize that the type of 'f2' in fact *didn't* expect
  a Char (and had an 'm'), so that the but its type is *not* in fact
  its declared type.
  
  I suppose it infers a type for 'f2' based on its use, and that then
  becomes the actual type, but it seems less confusing if it picked
  the declared type of 'f2' as its actual type.  Perhaps this is working
  as intended, but it it is confusing!  Especially the part about
  expected three but got three.
  
  Ideally I'd like to see too many arguments or at least expected
  (Char - m Bool) but actually 'm Bool'.  Actually I'd expect the
  other way: expected 'm Bool' but got (Char - m Bool)' but I think
  ghc has always done it backwards from how I expect.  It looks like
  it's substituting (-) for 'm', so maybe it's one of those things
  where ((-) a) is also a monad.
  ___
  Glasgow-haskell-users mailing list
  Glasgow-haskell-users@haskell.org
  http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
  
 
 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: confusing type error

2014-12-04 Thread Evan Laforge
On Thu, Dec 4, 2014 at 12:59 PM, migmit mig...@gmail.com wrote:
 It tries to get `m Bool` by applying f1 to three arguments: 0, 0, and 'a'. 
 Now, since `f2` has the type `Int - Float - n Bool`, where `n` is of kind 
 `* - *` (and an instance of `Monad` class, but it's not yet the time to look 
 for instances), we have `f2 0 :: Float - n Bool` and `f2 0 0 :: n Bool`. 
 Since that is applied to 'a', Haskell deduces that the last type should be 
 something like `Char - Something` — or, equivalently, `(-) Char Something`. 
 Therefore, it can see that `n` is in fact `(-) Char` and `Something` is 
 `Bool`. Therefore, `f2 0 0 'a' :: Bool`. But it is expecting `m Bool`, not 
 `Bool` — which is exactly what an error message says.

Right, that's what I suspected was happening.  The confusion arrises
because it guesses that 'm' should be (-), and that deduction then
leads to a dead-end.  But when it reports the problem, it uses its
guessed 'm', rather that backing up to the declared value.

But surely always backing up to the declared unspecialized value is no
good either, because then you get vague errors.  All the compiler
knows is that when it simplifies as far as it can, it winds up with a
/= b, it doesn't know that I would have been surprised by its path a
few steps back.

But arity errors are common, and intentionally instantiating a prefix
type constructor like 'm a' as (-) is probably much less common.  So
perhaps there could be a heuristic that treats (-) specially and
includes an extra clause in the error if it unified a type variable to
(-)?

I suspect the expected n but got n error is also due to the same
thing, it counts arrows on one side but inferred arrows on the other?
Or something?  In any case, it seems like the two sides are counting
inconsistently.
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Proving properties of type-level natural numbers obtained from user input

2014-12-04 Thread Alexander V Vershilov
Hi, Richard

Can you give some ideas or where to read how to properly use signletons
and unary naturals in order to be able to express such constraints?

Thanks
--
  Alexander

On 30 November 2014 at 23:26, Richard Eisenberg e...@cis.upenn.edu wrote:
 Hi Alexander,

 Nice idea to test against the set of known values. That's more type-safe than 
 anything I've thought of. I agree that it's a bit of a painful construction, 
 but I don't think we can do better with type-lits, as there is limited 
 reasoning ability that GHC can manage. If you want to switch to unary 
 naturals (`data Nat = Zero | Succ Nat`), then this can be built somewhat 
 nicely with singletons and without unsafeCoerce. But, of course, unary 
 naturals are very slow.

 By the way, the bug in the Proof2 version is a bug in GHC 7.8.3 (only in .3 
 -- not in .2 or in the soon-to-be .4) that allows you to write unsaturated 
 type families that don't work. Saying `LessThan255` without a parameter 
 should be a syntax error, but that check was accidentally turned off for 
 7.8.3, leading to a bogus type error.

 Thanks for sharing this work!
 Richard

 On Nov 28, 2014, at 5:27 PM, Alexander V Vershilov 
 alexander.vershi...@gmail.com wrote:

 Hi, Bas, Richard.

 I've played a bit with example, obvously first approach contained bugs,
 but seems that I have fixed it and here I have 2 approaches, one uses
 unsafeCoerce (as Richard suggested) another is safe but with bad complexity:

 Full file is quite big, so I'm not inlining it in mail, but here is a link:

 https://github.com/qnikst/haskell-fun/blob/master/typelevel-literals/Proof.lhs

 I wonder how far it's possible to go with singletons approach that I have
 not tried yet.

 --
 Alexander

 On 26 November 2014 at 10:15, Bas van Dijk v.dijk@gmail.com wrote:
 Hi Alexander,

 Thanks for your answer! This provides a lot of ideas how to proceed.

 I'm unsure about the following though:

 lessThen :: KnownNat m = SomeNat - Proxy m - Maybe (Proof (n = m) 
 (Proxy n))
 lessThen (SomeNat p) k
   | natVal p = natVal k = Just (Proof $ Tagged (Proxy :: Proxy n))
   | otherwise = Nothing

 Doesn't this mean lessThen returns a Proxy n for all (n :: Nat) and
 not just the Nat inside the SomeNat?

 I also see that p is only used for comparing it to k. It's not used to
 produce the return value.

 Cheers,

 Bas

 On 25 November 2014 at 19:55, Alexander V Vershilov
 alexander.vershi...@gmail.com wrote:
 Hi, Richard, Bas.

 Maybe I didn't spell it properly but my point was to create a data
 type that carry a proof
 without exposing it's constructor and having clever constructor only,
 then the only place
 where you need to check will be that constructor.

 Also it's possible to write in slightly clearer, but again it's
 possible to make a mistake here
 and it will be a false proof.

 lessThen :: KnownNat m = SomeNat - Proxy m - Maybe (Proof (n = m) 
 (Proxy n))
 lessThen (SomeNat p) k
   | natVal p = natVal k = Just (Proof $ Tagged (Proxy :: Proxy n))
   | otherwise = Nothing

 Of cause solution using singletons could solve this problem much better.

 --
 Alexander

 On 25 November 2014 at 21:34, Richard Eisenberg e...@cis.upenn.edu wrote:
 Hi Bas,

 I believe to do this right, you would need singleton types. Then, when 
 you discover that the number is bounded by 255, you would also discover 
 that the type is bounded by 255, and you'd be home free.

 Unfortunately, I there isn't currently a way to do comparison on 
 GHC.TypeLits Nats with singletons. (There is a module 
 Data.Singletons.TypeLits in the `singletons` package, but there's a 
 comment telling me TODO in the part where comparison should be 
 implemented.) If it were implemented, it would have to use unsafeCoerce, 
 as there's no built-in mechanism connecting runtime numbers with TypeLits.

 If I were you, I would just write `g` using unsafeCoerce in the right 
 spot, instead of bothering with all the singletons, which would have to 
 use unsafety anyway.

 The solution Alexander provides below doesn't quite build a proof, I 
 think. Tellingly, if we omit the `natVal p = 255` check, everything else 
 still compiles. Thus, the `Proof` type he uses can be built even if the 
 fact proven is false. That said, I don't know if my solution is any 
 better, crucially relying on unsafeCoerce.

 Richard

 On Nov 25, 2014, at 4:52 AM, Alexander V Vershilov 
 alexander.vershi...@gmail.com wrote:

 Hi,

 Following approach can work, the idea is to define a type that will
 carry a proof (constraint) that we want to check. Here I have reused
 Data.Tagged, but it's possible to introduce your own with concrete
 constraints.

 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE UndecidableInstances #-}
 import GHC.TypeLits
 import GHC.Exts
 import Data.Proxy
 import Data.Tagged
 import System.Environment

 New constraint carrying data type

 newtype Proof a