Logs: freenode/#haskell
| 2021-04-07 02:16:28 | <yahb> | olligobber: ; <interactive>:61:136: error:; * Couldn't match type `Integer' with `forall n. Num n => n'; Expected: Integer -> N; Actual: (forall n. Num n => n) -> N; * In the first argument of `(.)', namely `N'; In the expression: N . fromInteger; In an equation for `fromInteger': fromInteger = N . fromInteger |
| 2021-04-07 02:16:38 | <olligobber> | wrong one |
| 2021-04-07 02:16:41 | <olligobber> | % instance Num N where { N x + N y = N $ x + y; N x * N y = N $ x * y; abs (N x) = N (abs x); signum (N x) = N (signum x); fromInteger n = N (fromInteger n); negate (N x) = N (negate x)} |
| 2021-04-07 02:16:41 | <yahb> | olligobber: |
| 2021-04-07 02:16:50 | <olligobber> | % runN (1 + 2 * 3 :: N) |
| 2021-04-07 02:16:50 | <yahb> | olligobber: 7 |
| 2021-04-07 02:17:35 | <glguy> | % let x = N 10 * N 20 in (runN x :: Int, runN x :: Integer) |
| 2021-04-07 02:17:35 | <yahb> | glguy: (200,200) |
| 2021-04-07 02:17:36 | <Axman6> | % :t it |
| 2021-04-07 02:17:36 | <yahb> | Axman6: (Int, Integer) |
| 2021-04-07 02:17:50 | <glguy> | c-c-c-combo-breaker |
| 2021-04-07 02:18:00 | <Axman6> | ... surprised that worked (even it if wasn't the expression I wanted the type for) |
| 2021-04-07 02:18:01 | <Axman6> | ... surprised that worked (even it if wasn't the expression I wanted the type for) |
| 2021-04-07 02:18:03 | <Axman6> | uh |
| 2021-04-07 02:18:40 | <olligobber> | % let x = 2^65 in (runN x :: Int, runN x :: Integer) |
| 2021-04-07 02:18:40 | <yahb> | olligobber: (0,36893488147419103232) |
| 2021-04-07 02:19:09 | <glguy> | olligobber, maybe it would be less confusing if you made a struct for Num operations |
| 2021-04-07 02:19:13 | <glguy> | and then reimplemented your type as |
| 2021-04-07 02:19:28 | <glguy> | newtype N = N (forall a. NumOps a -> a) |
| 2021-04-07 02:19:43 | <olligobber> | maybe |
| 2021-04-07 02:20:03 | <glguy> | pull the type classes out of the mix; less magic |
| 2021-04-07 02:20:17 | → | shachaf joins (~shachaf@unaffiliated/shachaf) |
| 2021-04-07 02:20:18 | <olligobber> | yeah, but I like magic |
| 2021-04-07 02:20:29 | <glguy> | Is the goal to understand or be amazed? :) |
| 2021-04-07 02:20:30 | <monochrom> | olligobber: If you think of the suite of the methods of Num as a signature of an algebra, then "forall n. Num n => n" are expressions buildable from using only that signature. Similarly for Q. |
| 2021-04-07 02:21:04 | <olligobber> | are there actually other Quasi instances? or does haskell just use Q and magic happens? |
| 2021-04-07 02:21:07 | <monochrom> | perhaps s/from using only that signature/from only that algebra/ |
| 2021-04-07 02:21:53 | <glguy> | % :info Language.Haskell.TH.Syntax.Quasi |
| 2021-04-07 02:21:53 | <yahb> | glguy: type Quasi :: (* -> *) -> Constraint; class (MonadIO m, MonadFail m) => Quasi m where; qNewName :: String -> m Name; qReport :: Bool -> String -> m (); qRecover :: m a -> m a -> m a; qLookupName :: Bool -> String -> m (Maybe Name); qReify :: Name -> m Info; qReifyFixity :: Name -> m (Maybe Language.Haskell.TH.Fixity); qReifyType :: Name -> m Language.Haskell.TH.Type; qReifyInstances :: Name |
| 2021-04-07 02:22:06 | <glguy> | instance Quasi Q -- Defined in ‘Language.Haskell.TH.Syntax’ |
| 2021-04-07 02:22:06 | <glguy> | instance Quasi IO -- Defined in ‘Language.Haskell.TH.Syntax’ |
| 2021-04-07 02:22:35 | × | tzh quits (~tzh@c-24-21-73-154.hsd1.wa.comcast.net) (Ping timeout: 265 seconds) |
| 2021-04-07 02:23:23 | <monochrom> | Another one: "forall r. r -> (Int -> r) -> r" is equivalent to Maybe Int |
| 2021-04-07 02:23:31 | <olligobber> | oh, I know that one |
| 2021-04-07 02:23:52 | <monochrom> | And I can convert that to a need-type-class form too. |
| 2021-04-07 02:24:23 | <monochrom> | class M r where nothing :: r; just :: Int -> r |
| 2021-04-07 02:24:28 | × | hexfive quits (~hexfive@50.35.83.177) (Quit: i must go. my people need me.) |
| 2021-04-07 02:24:35 | <monochrom> | Then I have "forall r. M r => r" |
| 2021-04-07 02:24:58 | <olligobber> | huh |
| 2021-04-07 02:24:58 | × | todda7 quits (~torstein@athedsl-09242.home.otenet.gr) (Ping timeout: 240 seconds) |
| 2021-04-07 02:25:38 | <monochrom> | This is what glguy was saying. |
| 2021-04-07 02:25:54 | <olligobber> | oh... |
| 2021-04-07 02:26:02 | <olligobber> | the magic is fading away |
| 2021-04-07 02:26:17 | <olligobber> | but still, what Quasi monad does haskell use at compile time? |
| 2021-04-07 02:26:34 | <monochrom> | As Feymann said, I don't think there is a conflict between understanding and amazement. |
| 2021-04-07 02:26:52 | × | carlomagno quits (~cararell@148.87.23.11) (Quit: Leaving.) |
| 2021-04-07 02:27:04 | <monochrom> | The equivalence between the class version and the parameter version is beautiful |
| 2021-04-07 02:27:22 | <glguy> | olligobber, probably this one |
| 2021-04-07 02:27:29 | <glguy> | compiler/typecheck/TcSplice.hs |
| 2021-04-07 02:27:29 | <glguy> | 846:instance TH.Quasi TcM where |
| 2021-04-07 02:27:36 | × | machinedgod quits (~machinedg@135-23-192-217.cpe.pppoe.ca) (Ping timeout: 268 seconds) |
| 2021-04-07 02:27:56 | <olligobber> | wait, so Num can be a type? like `forall a. ((a -> a -> a) -> (a -> a -> a) -> (a -> a) -> (a -> (a,a)) -> (Integer -> a) -> (a -> a)) -> a |
| 2021-04-07 02:28:00 | <glguy> | or:libraries/ghci/GHCi/TH.hs |
| 2021-04-07 02:28:01 | <glguy> | 163:instance TH.Quasi GHCiQ where |
| 2021-04-07 02:28:29 | <olligobber> | aww, I was hoping it just used Q and somehow extracted what it needed from the universal type |
| 2021-04-07 02:28:58 | <monochrom> | For Q and Quasi, what you're seeing is dependency inversion, i.e., both user and implementer code to the common interface Quasi, don't assume anything more concrete on either side (would be too much coupling) |
| 2021-04-07 02:28:59 | <olligobber> | I don't get why it uses Q Exp instead of Quasi m => m Exp though |
| 2021-04-07 02:29:21 | <glguy> | olligobber, actually they like the type synonym ExpQ |
| 2021-04-07 02:29:41 | <glguy> | probably just because doing it the way you said would be needlessly noisy |
| 2021-04-07 02:30:10 | <monochrom> | The newtype wrapper is more convenient when passing around as parameter. |
| 2021-04-07 02:30:17 | <olligobber> | hmm |
| 2021-04-07 02:30:57 | <olligobber> | I guess you rarely have a concrete type satisfying Quasi on the user's end, so using Q is more convenient |
| 2021-04-07 02:31:02 | <monochrom> | Relieves user from needing RankNTypes when you have "Q a -> Q a -> ..." instead of "(forall m. ...) -> (forall m. ...) -> ..." |
| 2021-04-07 02:31:27 | <olligobber> | but with a class like Num you have plenty of types satisfying Num, so N would be inconvenient |
| 2021-04-07 02:31:50 | <glguy> | The issue with Num is that there are a bunch of non-Num operations you've likely to want to use |
| 2021-04-07 02:32:01 | <olligobber> | I was imagining Q a -> Q a -> Q a would be replaced by Quasi m => m a -> m a -> m a, but I guess those types aren't identical |
| 2021-04-07 02:32:09 | <glguy> | also it's more efficient to know what type things are being done at |
| 2021-04-07 02:32:38 | <glguy> | they aren't identical, but practially the later would be what you'd need |
| 2021-04-07 02:33:21 | <olligobber> | oh, and I made a useless type |
| 2021-04-07 02:33:33 | <olligobber> | newtype S = S {runS :: forall s. Show s => s} |
| 2021-04-07 02:33:40 | <monochrom> | :) |
| 2021-04-07 02:33:41 | <olligobber> | I don't think it has any values |
| 2021-04-07 02:33:59 | <olligobber> | except undefined |
| 2021-04-07 02:34:04 | <olligobber> | and error stuff |
| 2021-04-07 02:35:41 | × | RusAlex quits (~Chel@unaffiliated/rusalex) (Ping timeout: 240 seconds) |
| 2021-04-07 02:36:39 | <olligobber> | the thing is, something of type N -> N cannot be turned into Num n => n -> n |
| 2021-04-07 02:36:50 | <olligobber> | so it's somehow stronger |
| 2021-04-07 02:37:06 | <monochrom> | For "forall r. C r => r" to have values, you want the class C to have some methods being smart constructors. |
| 2021-04-07 02:37:07 | <olligobber> | it guarantees that whatever you give it has to be a number and nothing but |
| 2021-04-07 02:37:34 | <monochrom> | For example my M class has two smart constructors, nothing and just. |
| 2021-04-07 02:37:41 | <monochrom> | For example Num has fromInteger. |
| 2021-04-07 02:37:48 | <olligobber> | yeah |
| 2021-04-07 02:38:17 | <monochrom> | You know what, since that's the only constructor, "forall n. Num n => n" is equivalent to Integer. |
| 2021-04-07 02:38:33 | <olligobber> | try |
| 2021-04-07 02:38:35 | <olligobber> | true |
| 2021-04-07 02:38:49 | <olligobber> | so it's like the initial object in a way |
| 2021-04-07 02:38:51 | <glguy> | monochrom, doesn't olligobber's 2^65 example show that that's not quite true? |
| 2021-04-07 02:39:13 | <glguy> | it's the journey, not the destination |
| 2021-04-07 02:39:33 | <olligobber> | nah, if you replace runN with fromInteger you get the same result |
| 2021-04-07 02:39:47 | → | RusAlex joins (~Chel@unaffiliated/rusalex) |
| 2021-04-07 02:40:03 | <glguy> | % let x = 2^65 in (runN x :: Int, runN x :: Integer) |
| 2021-04-07 02:40:03 | <yahb> | glguy: (0,36893488147419103232) |
| 2021-04-07 02:40:18 | <glguy> | so clearly x couldn't be represented with a mere Integer |
| 2021-04-07 02:40:20 | <olligobber> | % let x = 2^65 in (fromInteger x :: Int, fromInteger x :: Integer) |
| 2021-04-07 02:40:20 | <yahb> | olligobber: (0,36893488147419103232) |
| 2021-04-07 02:40:26 | <olligobber> | looks the same to me |
| 2021-04-07 02:41:28 | <glguy> | % let x = signum (2^65) in (runN x :: Int, runN x :: Integer) |
| 2021-04-07 02:41:28 | <yahb> | glguy: (0,1) |
| 2021-04-07 02:41:33 | <glguy> | ok, now do yours |
| 2021-04-07 02:41:48 | <olligobber> | % let x = signum (2^65) in (fromInteger x :: Int, fromInteger x :: Integer) |
All times are in UTC.