Newest at the top
2024-10-26 11:27:54 +0200 | Sgeo | (~Sgeo@user/sgeo) (Read error: Connection reset by peer) |
2024-10-26 11:27:08 +0200 | ash3en1 | ash3en |
2024-10-26 11:25:40 +0200 | <Leary> | Not really. Just pull through whatever ExceptT has that you need. |
2024-10-26 11:24:42 +0200 | ash3en1 | (~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en |
2024-10-26 11:24:34 +0200 | ash3en | (~Thunderbi@146.70.124.222) (Ping timeout: 248 seconds) |
2024-10-26 11:24:33 +0200 | merijn | (~merijn@128-137-045-062.dynamic.caiway.nl) (Ping timeout: 248 seconds) |
2024-10-26 11:24:31 +0200 | <haskellbridge> | <tux314159> okay, thanks. but then this kind of runs into the dreaded n^2 instances issue with mtl doesn't it, I have to add every constraint I want to into the deriving |
2024-10-26 11:21:44 +0200 | tomsmeding | is afk for a while |
2024-10-26 11:20:58 +0200 | tromp | (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) |
2024-10-26 11:20:44 +0200 | <tomsmeding> | so yes, the same after peeling off newtype constructors |
2024-10-26 11:20:34 +0200 | <tomsmeding> | it works when your newtype is _coercible_ (as in `Data.Coerce`) to the thing you put after `via` |
2024-10-26 11:20:09 +0200 | <haskellbridge> | <tux314159> I see, this thing works when the instances are equivalent when you peel back the newtype cosntructor? |
2024-10-26 11:20:09 +0200 | <Leary> | via ExceptT e m |
2024-10-26 11:20:04 +0200 | merijn | (~merijn@128-137-045-062.dynamic.caiway.nl) merijn |
2024-10-26 11:19:36 +0200 | <tomsmeding> | deriving (Functor, Applicative, Monad) via (ExceptT e m a) |
2024-10-26 11:19:12 +0200 | <tomsmeding> | hm, right |
2024-10-26 11:18:54 +0200 | <tomsmeding> | (in yours, it is not because it's inside an application to 'm') |
2024-10-26 11:18:53 +0200 | <Leary> | Or refer to the transformers with DerivingVia. Which gives you better type roles too. |
2024-10-26 11:18:44 +0200 | <tomsmeding> | the 'a' that is the last type variable of 'App' must also be the last type variable in the type of the field |
2024-10-26 11:18:29 +0200 | <tomsmeding> | write your full stack, then put _that_ inside the newtype |
2024-10-26 11:18:17 +0200 | <tomsmeding> | `newtype App e a = App (ExceptT e IO a)` or something |
2024-10-26 11:18:00 +0200 | <tomsmeding> | ah, the idea is that you put the existing transformers _inside_ your newtype |
2024-10-26 11:17:41 +0200 | <haskellbridge> | <tux314159> oh I was trying `newtype ExceptT' e m a = ExceptT' { runExceptT' :: m (Either e a) } deriving (Functor, Applicative, Monad)` but I guess that's not the correct form? |
2024-10-26 11:16:55 +0200 | <tomsmeding> | https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/newtype_deriving.html#generalising-… , for reference |
2024-10-26 11:15:46 +0200 | <tomsmeding> | it indeed needs to be in the appropriate form |
2024-10-26 11:15:34 +0200 | <tomsmeding> | what is your newtype precisely? |
2024-10-26 11:15:25 +0200 | <haskellbridge> | <tux314159> "couldn't eta reduce enough" or something |
2024-10-26 11:15:12 +0200 | <tomsmeding> | deriving (Functor, Applicative, Monad) |
2024-10-26 11:15:06 +0200 | <tomsmeding> | that's what you have -XGeneralizedNewtypeDeriving for |
2024-10-26 11:14:55 +0200 | <tomsmeding> | separate implementation from interface |
2024-10-26 11:14:50 +0200 | <tomsmeding> | i.e. write your own newtype that internally uses the convenience of mtl stuff, and then write your app in terms of that newtype |
2024-10-26 11:14:48 +0200 | <haskellbridge> | <tux314159> oh I tried that but it wants me to go ahead and define functor/appl/monad for my wrapper and it seems super high-effort for something os simple |
2024-10-26 11:14:29 +0200 | <tomsmeding> | making newtypes around the monads from transformers/mtl is what people generally recommend anyway |
2024-10-26 11:14:14 +0200 | ljdarj | (~Thunderbi@user/ljdarj) ljdarj |
2024-10-26 11:14:11 +0200 | <tomsmeding> | make your own newtype around ExceptT? |
2024-10-26 11:14:08 +0200 | <haskellbridge> | <tux314159> but it's more specific so... can I just enable OverlappingInstances xD |
2024-10-26 11:13:51 +0200 | <haskellbridge> | ... long message truncated: https://kf8nh.com/_heisenbridge/media/kf8nh.com/gwoFNkeSYhMaeyAOqJyRqQGR/gklQIOtpBMU (3 lines) |
2024-10-26 11:13:51 +0200 | <haskellbridge> | <tux314159> instance Monad m => MonadFail (ExceptT String m) where |
2024-10-26 11:13:29 +0200 | <yahb2> | \m -> do { Nothing <- m; return "ok" } ; :: MonadFail m => m (Maybe a) -> m String |
2024-10-26 11:13:29 +0200 | <tomsmeding> | % :t \m -> do { Nothing <- m; return "ok" } |
2024-10-26 11:13:27 +0200 | <Rembane> | MonadFail is very good for making do-notation more succinct when only the happy flow is cared about |
2024-10-26 11:13:26 +0200 | <haskellbridge> | <tux314159> actually that's precisely my usecase xD |
2024-10-26 11:12:57 +0200 | <tomsmeding> | for ExceptT, perhaps the reasoning is "ExceptT is for explicit exceptions, and the fail from MonadFail is called also in perhaps unintended situations like partial pattern matches" |
2024-10-26 11:12:56 +0200 | <Rembane> | \o/ Orphan instances ftw! \o/ |
2024-10-26 11:12:29 +0200 | merijn | (~merijn@128-137-045-062.dynamic.caiway.nl) (Ping timeout: 260 seconds) |
2024-10-26 11:12:24 +0200 | <tomsmeding> | I think for Either the motivation is "there are arguments for an against a MonadFail instance for `Either String a`, so in dispute, let's do nothing" |
2024-10-26 11:11:31 +0200 | <tomsmeding> | (indeed, it has none) |
2024-10-26 11:11:16 +0200 | <tomsmeding> | similarly Either doesn't have the MonadFail instance you might expect |
2024-10-26 11:11:04 +0200 | <tomsmeding> | ExceptT doesn't necessarily have String as the first component |
2024-10-26 11:10:41 +0200 | <haskellbridge> | Hmm is there any reason the MonadFail instance for ExceptT has `fail = ExceptT . fail`? Seems a bit odd, since the whole point of exceptT is to handle these, not bubble them up to the next monad |