Selecting some of One where there're none of Many - ihp

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]

Related

List split in Elm

Write a function to split a list into two lists. The length of the first part is specified by the caller.
I am new to Elm so I am not sure if my reasoning is correct. I think that I need to transform the input list in an array so I am able to slice it by the provided input number. I am struggling a bit with the syntax as well. Here is my code so far:
listSplit: List a -> Int -> List(List a)
listSplit inputList nr =
let myArray = Array.fromList inputList
in Array.slice 0 nr myArray
So I am thinking to return a list containing 2 lists(first one of the specified length), but I am stuck in the syntax. How can I fix this?
Alternative implementation:
split : Int -> List a -> (List a, List a)
split i xs =
(List.take i xs, List.drop i xs)
I'll venture a simple recursive definition, since a big part of learning functional programming is understanding recursion (which foldl is just an abstraction of):
split : Int -> List a -> (List a, List a)
split splitPoint inputList =
splitHelper splitPoint inputList []
{- We use a typical trick here, where we define a helper function
that requires some additional arguments. -}
splitHelper : Int -> List a -> List a -> (List a, List a)
splitHelper splitPoint inputList leftSplitList =
case inputList of
[] ->
-- This is a base case, we end here if we ran out of elements
(List.reverse leftSplitList, [])
head :: tail ->
if splitPoint > 0 then
-- This is the recursive case
-- Note the typical trick here: we are shuffling elements
-- from the input list and putting them onto the
-- leftSplitList.
-- This will reverse the list, so we need to reverse it back
-- in the base cases
splitHelper (splitPoint - 1) tail (head :: leftSplitList)
else
-- here we got to the split point,
-- so the rest of the list is the output
(List.reverse leftSplitList, inputList)
Use List.foldl
split : Int -> List a -> (List a, List a)
split i xs =
let
f : a -> (List a, List a) -> (List a, List a)
f x (p, q) =
if List.length p >= i then
(p, q++[x])
else
(p++[x], q)
in
List.foldl f ([], []) xs
When list p reaches the desired length, append element x to the second list q.
Append element x to list p otherwise.
Normally in Elm, you use List for a sequence of values. Array is used specifically for fast indexing access.
When dealing with lists in functional programming, try to think in terms of map, filter, and fold. They should be all you need.
To return a pair of something (e.g. two lists), use tuple. Elm supports tuples of up to three elements.
Additionally, there is a function splitAt in the List.Extra package that does exactly the same thing, although it is better to roll your own for the purpose of learning.

Why I can't use matched variable instead of a variable value?

Here is an example from here. The code looks like that:
sum : (single : Bool) -> isSingleton single -> Nat
sum True x = x
sum False [] = 0
sum False (x :: xs) = x + sum False xs
I've tried to use single instead of False in the last line. But it fails. I think the problem is that the type of sum single xs is either Nat or List Nat, but + requires only Nat operands. But we are inside a clause where single equals False either way. Shouldn't Idris infer it? Why I can't use single here? Is there some reason for it?
Here is the error:
main.idr:14:23-41:
|
14 | sum False (x :: xs) = x + (sum single xs)
| ~~~~~~~~~~~~~~~~~~~
When checking right hand side of Main.sum with expected type
Nat
When checking argument single to Main.sum:
No such variable single
Upd:
It looks like that the problem here is that I can't directly access the variable from type definition. Then I've tried to use implicit arguments like that:
sum : (single : Bool) -> isSingleton single -> Nat
sum True x = x
sum False [] = 0
sum {single} False (x :: xs) = x + sum single xs
It doesn't help either. Maybe I'm using it wrong. Also I've tried the simplest possible variation like that:
sum : (single: Bool) -> isSingleton single -> Nat
sum s list = case s of
True => list
False => case list of
[] => 0
(x::xs) => x + (sum s xs)
But it doesn't compile either:
|
16 | (x::xs) => x + (sum s xs)
| ~~~~~~~~
When checking right hand side of Main.case block in case block in sum at main.idr:12:19 at main.idr:14:19-22 with expected type
Nat
When checking an application of Main.sum:
Type mismatch between
List Nat (Type of xs)
and
isSingleton s (Expected type)
It looks a bit weird for me, because from one point Idris could prove many interesting and complex things, and from another such a simple thins is unavailable. Or maybe I'm doing it wrong.
It's not so much that it can't infer the type of single, as single isn't in scope on the RHS. You could use a named pattern with single on the LHS
sum : (single : Bool) -> isSingleton single -> Nat
sum True x = x
sum False [] = 0
sum single#False (x :: xs) = x + sum single xs
I can't see a way to avoid the named pattern in this case and just use
sum single (x :: xs) = x + sum single xs
as Idris doesn't infer it's a List Nat without the False. I get
|
8 | sum single (x :: xs) = x + sum single xs
| ~~~~~~~~~~~~~~~~~~~~
When checking left hand side of Main.sum:
When checking an application of Main.sum:
Can't disambiguate since no name has a suitable type:
Prelude.List.::, Prelude.Stream.::

Elm: Partial Function Application and Let

The Beginning Elm - Let Expression page builds on the previous page, but it doesn't cover how to update the main function, written in forward function notation, which was:
main =
time 2 3
|> speed 7.67
|> escapeEarth 11
|> Html.text
to include the new fuelStatus parameter.
The compiler complains about a type mismatch, which is correct, as escapeEarth now has a third argument, which is a string.
As stated on that site "The forward function application operator takes the result from the previous expression and passes it as the last argument to the next function application."
In other words, how do I write this:
Html.text (escapeEarth 11 (speed 7.67 (time 2 3)) "low")
using forward notation?
Also, why doesn't this print "Land on droneship", along with "Stay in orbit"? It only prints "Stay in orbit":
module Playground exposing (..)
import Html
escapeEarth velocity speed fuelStatus =
let
escapeVelocityInKmPerSec =
11.186
orbitalSpeedInKmPerSec =
7.67
whereToLand fuelStatus =
if fuelStatus == "low" then
"Land on droneship"
else
"Land on launchpad"
in
if velocity > escapeVelocityInKmPerSec then
"Godspeed"
else if speed == orbitalSpeedInKmPerSec then
"Stay in orbit"
else
"Come back"
speed distance time =
distance / time
time startTime endTime =
endTime - startTime
main =
Html.text (escapeEarth 11 (speed 7.67 (time 2 3)) "low")
I think what you need is
main =
time 2 3
|> speed 7.67
|> \spd -> escapeEarth 11 spd "low"
|> Html.text
In other words you define a little anonymous function to insert the value correctly. You may want to look at whether the escapeEarth function should be defined with a different order.
An alternative if you love 'point free' would be
main =
time 2 3
|> speed 7.67
|> flip (escapeEarth 11) "low"
|> Html.text
Some would argue that this is less clear though
As for your second question you have defined functions in your let statement but never actually used it

What does _ mean in Elm?

I'm looking at the zip example on http://elm-lang.org/examples/zip and I had a question about what exactly the _ means in Elm.
zip : List a -> List b -> List (a,b)
zip xs ys =
case (xs, ys) of
( x :: xs', y :: ys' ) ->
(x,y) :: zip xs' ys'
(_, _) ->
[]
My hunch is that it means "everything else" but does that mean any valid value? What if there is no value?
_ is used to match anything where you don't care about the value, so it's commonly used to match the "everything else" case.
In your example code (_, _) will match any tuple with 2 values in it. Note that it could also be replaced with just _ since you end up not caring about either value. A more illustrative example would be where you care about one value from the tuple but not the other, for example the implementation of fst in the core package
fst : (a,b) -> a
fst (a,_) =
a
We don't care about the second value in the tuple, so it just matches with an _ in that position.
There is no null or undefined in Elm, so you don't have to worry about there being "no value" (if something would have no value, the Maybe type is used).

Find all Change Combinations (money) in OCaml

I have a some OCaml code that finds all combinations of change given a change amount. I have most of the code working, however I am not able to figure out how this recursive function will actually return the possible change combinations.
let change_combos presidents =
let rec change amount coinlist = match amount with
|0 -> [[]] (*exits when nothing*)
|_ when (amount < 0) -> [] (*exits when less than 0*)
|_ -> match coinlist with
|[] -> [] (*Returns empty list, exits program*)
(*h::f -> something, using [25;10;5;1] aka all change combinations...*)
(*using recursion, going through all combinations and joining lists returned together*)
let print_the_coin_matrix_for_all_our_joy enter_the_matrix =
print_endline (join "\n" (List.map array_to_string enter_the_matrix));;
Thanks for the help, let me know if I need to clarify something :)
It is a bit confusing what you're looking for. I believe that you want to generate a list of all the combinations of a list? You should think about the recursion and how to generate the individual elements. Start with the input type, and how you'd generate successive elements by reducing the problem space.
let rec generate lst = match lst with
| [] -> []
| h::t -> [h] :: (List.map (fun x -> h::x) (generate t)) # (generate t)
If the list is [] there are no combinations. If we have an element we generate all combinations without that element and base our construction on that assumption. The components fall into place at this point. Concatenate the list of combinations of t with the combinations of t and h cons'd onto each and a singleton of h.