Home freenode/#haskell: Logs Calendar

Logs: freenode/#haskell

←Prev  Next→ 502,152 events total
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.