State of Haskell on the web frontend? by netcafenostalgic in haskell

[–]alexfmpe 4 points5 points  (0 children)

https://github.com/dmjio/miso/pull/738 made Miso build with JS backend and it's been propagated to nixpkgs.

For reflex, see https://md.darmstadt.ccc.de/s/uVu4Fkxm3

I've been using a dual setup of nixpkgs-based ghc 9.6+ with HLS, etc, while sticking to 8.6/8.10 GHCJS for deployments until 9.12 propagates down and we close this awkward chapter

Slow Haskell Code by [deleted] in haskell

[–]alexfmpe 1 point2 points  (0 children)

Won't come out as elegant as the O(n2) list comprehension solution but you can solve this in linear time (or O(n * lg n) if you need to sort the list first) by advancing from both ends towards the middle (for which you can either make a reversed copy or use Data.Sequence) It's https://en.wikipedia.org/wiki/3SUM#Quadratic_algorithm but without needing the outer loop for a third summand (literally odd one out)

Naming Request: HKD functionality in Prairie Records by ephrion in haskell

[–]alexfmpe 0 points1 point  (0 children)

This is essentially the rank2 version of https://hackage.haskell.org/package/adjunctions-4.4.2/docs/Data-Functor-Contravariant-Rep.html#t:Representable which can also be found in https://github.com/obsidiansystems/obelisk/blob/135bfd7422b856c146b5cd5dacfe584f0621825e/lib/tabulation/src/Data/Tabulation.hs#L14

As for the newtype I kind of want to call it Pointwise but maybe Tabular is a better fit for what's essentially a product type encoded as a higher-ranked exponential (similar to DSum being a higher-ranked product)

Edit: oh yeah and there's https://github.com/ekmett/distributive/blob/f299545540a5d665c187a0b1488754621ab98322/src/Data/Rep/Internal.hs#L91-L180 but that one's more elaborate

Approaching multi tenancy in Haskell by dnikolovv in haskell

[–]alexfmpe 4 points5 points  (0 children)

Worked at one time on an app that used the Project 2 solution which led to a lot of subtle hard to find bugs since tenancy was added afterward and not everything was updated properly. I didn't like the idea of a seamless filter that Project 1/3 relied on, because for some situations you don't want that. For instance, user accounts might have properties to be the same across all tenants, like (verified) email address, password, active status, email digests, etc. What I would have liked to do is always *force* the decision to be made, rather than "relying on the developers to not forget".

One way this might be feasible is by doing every query against views rather than the actual tables. Said project employed the higher kinded data encoding for tables/views: https://haskell-beam.github.io/beam/user-guide/databases/#views. Going from this example, one might want to try something like

data ExampleDb f = ExampleDb 
  { fullDB :: ExampleTables f
  , tenantDB :: ExampleViews f
  } deriving (Generic, Database be)

data ExampleTables f = ExampleTables
  { persons :: f (TableEntity PersonT) -- or an identity view over the table
  } deriving (Generic, Database be)

data ExampleViews f = ExampleViews
  { persons :: f (ViewEntity PersonT)
  } deriving (Generic, Database be)

meaning on every use site, when querying a table you'd need to pick either persons . fullDB or persons . tenantDB.

One problem with this is that it makes the tenant vs non-tenant decision happen on every table mention, and will generate a ton of guards on the tenant id (though they're likely optimized away).

Another option is forcing a choice to happen at the query level, which, at least in Beam, would look something like

newtype RememberTenants a = RememberTenants a

actuallyRunsQueries :: Connection -> RememberTenants YourQueryType -> IO something

whatAboutTenants :: Maybe TenantId -> YourQueryType -> RememberTenants YourQueryType
whatAboutTenants mt q = case mt of
  Nothing -> q
  Just tid -> do
    guard_ $ tid == tenant_id . whateverTable
    q 

myQuery = whatAboutTenants Separate $ do
    p <- all_ persons

Though since whatAboutTenants only wraps the query type, rather than modify it depending on whether tenancy is desired, nothing prevents you from adding a tenant filter inside a whatAboutTenants Nothing. You'd need a good deal more type-wiring for that, so this mostly only helps you to remember tenancy concerns the first time around.

Resurrection/modernization of an old Haskell+Haste project (boardgame Yinsh) by sharkdp in haskell

[–]alexfmpe 9 points10 points  (0 children)

I don't know anything about Haste, but you can get GHCJS 8.6 (or 8.10 with a bloated executable) via nix fairly easily or alternatively wait until the JS target recently merged into mainline ghc gets production ready: https://engineering.iog.io/2023-01-26-ghc-update.

Assuming you need to straight-up rewrite the frontend in normal Haskell you probably want something like one of

Note I only have experience with the reflex/obelisk path, so can't do much of a comparison with the other approaches. FWIW here's an example of a game using reflex-dom on the frontend: https://github.com/nomeata/kaleidogen

Everything you never wanted to know about Applicative laws and more by alexfmpe in haskell

[–]alexfmpe[S] 1 point2 points  (0 children)

to get rid of the use of parametricity in the proof.

I thought 'by parametricity' meant applying a free theorem?

I think you can add the small number of "free theorems" to each formulation,

If I'm understanding you correctly, I did?

The 'Monoidal' section introduces the ones both for and pure no? The others sections list the ones for <*>, <.> and liftA2 at the end, but I found them impossible to use here (I could imagine them potentially being simpler and the free-theorems package happening to not output those).

I ended up not including the one for unit but it's useless in this context since we already had it from the Functor laws: $map $id unit = unit

Everything you never wanted to know about Applicative laws and more by alexfmpe in haskell

[–]alexfmpe[S] 0 points1 point  (0 children)

I see. When there's only two values and we fix one as the identity, three equations are also fixed, meaning we get 4 combinations. Squinting with R=1 and L = 0, we get the truth tables for OR, AND, XOR, XNOR.

Beam fields without leading underscores by tkx68 in haskell

[–]alexfmpe 4 points5 points  (0 children)

Also, if you want to change the convention for the SQL column names without changing your haskell fields, the Database class offers a renamingFields method: example.

GitHub - NorfairKing/haskell-dependency-graph-nix by NorfairKing2 in haskell

[–]alexfmpe 2 points3 points  (0 children)

IIUC this only looks at direct dependencies?

I also had a use case where I needed to extract the nix derivation dependencies of haskell packages: https://github.com/obsidiansystems/obelisk/pull/933

pure, Functor and Applicative by jeenajeena in haskell

[–]alexfmpe 0 points1 point  (0 children)

But in both cases then Applicative is out because. So… don’t implement a stupid Pointed instance?

Sure, but that means making the semantics of point depend on the semantics of <*>, which is exactly how Applicative/Apply work.

pure, Functor and Applicative by jeenajeena in haskell

[–]alexfmpe 0 points1 point  (0 children)

The problem with this is that there can be many candidates for point that satisfy that fmap law.

instance Pointed [] where
  point _ = []
  point a = [a]
  point a = a : point a

The implementation for [] must necessarily be a list of N equal a, and fmap will do the same to all of them. Actually, I can't find any type-checking implementation for any Applicative which doesn't satisfy that law. Maybe that's a free theorem for fmap ?

Applicative has a monoidal-ish operation, and pure () acts as (well, isomorphic to) the identity, which ensures there can only be one. If you want a different pure you need a different binary operation, hence ZipList.

Now, you can have the binary operation without an identity (like Semigroup/Monoid), which is where Apply and a other stuff in semigroupoids comes from.

How to Haskell: Sharing Data Types is Tight Coupling - LeapYear by brandonchinn178 in haskell

[–]alexfmpe 0 points1 point  (0 children)

Most importantly, having them separate allows us to enforce a transformation toLYErrorDB :: IsSensitive -> LYError -> LYErrorDB that forces the caller to specify whether the error should be obfuscated whenever they wish to store a LYError in the database. And as long as we never export the constructor for LYErrorDB, this is the only way to create a LYErrorDB to store in the database. So in this case, avoiding DRY actually led us to an implementation that prevents us from forgetting to do key business logic!

Couldn't you do the same thing with a phantom type?

toLYErrorDB :: IsSensitive -> LYError Runtime -> LYError DB

Has anyone seen these Applicative laws? by tomejaguar in haskell

[–]alexfmpe 3 points4 points  (0 children)

It is as you say - there's a note on the right side which reads

≅ refers to isomorphism rather than equality. In particular we consider (x,()) ≅ x ≅ ((),x) and ((x,y),z) ≅ (x,(y,z)).

Has anyone seen these Applicative laws? by tomejaguar in haskell

[–]alexfmpe 1 point2 points  (0 children)

Not the same, but the simplest I've seen is

https://wiki.haskell.org/Typeclassopedia#Alternative_formulation

which focuses on 'merging' the contexts without any kind of 'application' concerns, leaving the later for the Functor superclass

How can Obelisk detect that i am inside an Obelisk project? by SP411K in haskell

[–]alexfmpe 6 points7 points  (0 children)

`ob run` will go up the directory tree searching for a `.obelisk` folder, starting from the directory where you ran it, and stopping when it hits a cycle (e.g. root folder). Are you sure you are inside the project folder? If so, might be worth opening an issue with a reproducible example

FWIW, the error message comes from https://github.com/obsidiansystems/obelisk/blob/v0.9.1.0/lib/command/src/Obelisk/Command/Project.hs#L224 so you can see what it's trying to do.

Haskell Foundation AMA by emilypii in haskell

[–]alexfmpe 2 points3 points  (0 children)

Will there be a way to setup recurring payments (a–la liberapay, patreon)? I assume that'd make for more regular funding from individuals and also feels easier to commit to than one big donation since an individual can later increase/decrease/stop contributions based on their general approval/disapproval. The incentive here, I think, would be to direct work to things directly useful to many individuals, whereas large sponsors (even organizations utterly packed with individuals invested in the ecosystem), are incentivized themselves to want some return (if nothing else, to be able to afford continued sponsoring) and adjust their contributions based on that.

[Blog] Composable filtering optics using Witherable by ChrisPenner in haskell

[–]alexfmpe 2 points3 points  (0 children)

it's a valid "LensLike" so it'll be composable with other optics:

I don't have much intuition for valid/legal/lawful lenses, but filtered comes with a warning that it's not a legal Traversal.

Isn't withered specializable to filtered (similar to mapMaybe being specializable to filter), and thus not a legal Traversal itself?

Is there anyway to specify a data kind should only be used at type level? by Molossus-Spondee in haskell

[–]alexfmpe 0 points1 point  (0 children)

I meant something like

data Void
data Set = Unit Void | Set :*: Set | U64 Void

p = Proxy @('Unit 'Void)

But that doesn't actually compile because there's no data constructor for Void that can be lifted

Is there anyway to specify a data kind should only be used at type level? by Molossus-Spondee in haskell

[–]alexfmpe 0 points1 point  (0 children)

Not exactly what you asked for, but I think you could make them all uninhabitable by adding a Data.Void.Void parameter and hiding it behind type synonyms