0

I'm trying to find domains that don't have any usernames with a given name, that is free domains. Hopefully there's a solution to this that doesn't require 2 separate queries, but I also ran into a problem with type system.

-- error Couldn't match type 'IO [Domain]' with '[[Domain]]', points to beginning of filter

            Just term -> do
                usernames <- query @Username
                    |> filterWhere (#name, term) |> fetch >>= collectionFetchRelated #domainId
                domains <- search |> filter \x->case find (\y->get #domainId x == get #domainId y) usernames of
                    Just _ -> True
                    Nothing -> False
                render IndexView {..}
janat08
  • 1,725
  • 2
  • 16
  • 27

1 Answers1

0

The error -- error Couldn't match type 'IO [Domain]' with '[[Domain]]', points to beginning of filter is happening because of the arrow notation here:

                domains <- search |> filter \x->case find (\y->get #domainId x == get #domainId y) usernames of
                    Just _ -> True
                    Nothing -> False

As this is not doing any IO, it needs to use a let:

                let domains = search |> filter \x->case find (\y->get #domainId x == get #domainId y) usernames of
                    Just _ -> True
                    Nothing -> False

Now the type of domains is [[Domain]] (a list of list of domains). Likely we want [Domain] (just a normal list of domains).

We can use concat for that purpose:

                let domains = search
                        |> filter ( \x-> case find (\y->get #domainId x == get #domainId y) usernames of
                                Just _ -> True
                                 Nothing -> False
                            )
                        |> concat

Now the type error should be gone.


Hopefully there's a solution to this that doesn't require 2 separate queries

Yes this is doable as well with a handwritten query:

domains <- sqlQuery "SELECT domains.* FROM domains WHERE (SELECT COUNT(*) FROM usernames WHERE usernames.domain_id = domains.id AND usernames.name = ?) = 0" [term]
Marc Scholten
  • 1,351
  • 3
  • 5
  • let domains = search is IO, and appending concat somehow made it worse to produce [[[Domains]]] after I also added brackets in front of filter. Nevertheless as far as IHP goes, this is solved. – janat08 Sep 09 '21 at 13:31