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 {..}
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]