Maybe.map over a function that returns a pair - elm

I have a function with Type signature
a -> b -> (a, b)
And I have
Maybe a
How can I map such a function such that I can get
(a->b->(a,b)) -> Maybe a -> (Maybe a, b)

You need to slightly change the function definition
g : (a -> b -> (a,b)) -> Maybe a -> b -> (Maybe a, b)
g f ma b =
case ma of
Nothing -> (Nothing, b)
Just a ->
let
r = f a b
in
(Just (first r), second r)

Related

Typed Lambda Calculus

I want to find the type of the lambda expression \x y -> x y y. I proceed as follows.
We go in the reverse order of operations and "unpack" the expression. Assume the whole expression has type A. Then let y have type x1 and \x y -> x y have type B. Then A = B -> x1
We already know the type of y, and let \x y -> x be of the type C. Then B = C -> x1.
The type of \x y -> x is obviously x1->x2->x1. This is given to us in the previous exercise and makes sense because this expression takes in two arguments and returns the first.
Putting it all together we have that:
A = B -> x1 = C -> x1 -> x1 = (x1 -> x2 -> x1) -> x1 -> x1
The correct answer is somehow:
(x1 -> x1 -> x2) -> x1 -> x2
What am I doing wrong?
Here I just write stuff's types under it and go from there:
foo = \x y -> x y y
foo x y = x y y
a b : c
a b b : c
a b : b -> c
a : b -> b -> c
foo : a -> b -> c
~ (b -> b -> c) -> b -> c
And another one:
bar = \x y -> x (y x)
bar x y = x (y x)
a b : c
a (b a) : c
---------
b a : d
b : a -> d
a : d -> c
bar : a -> b -> c
~ (d -> c) -> ( a -> d) -> c
~ (d -> c) -> ((d -> c) -> d) -> c
But,
baz x = x x
a a a : b
a : a -> b
baz : a -> b
~ (a -> b) -> b
~ ((a -> b) -> b) -> b
~ (((a -> b) -> b) -> b) -> b
........
is an "infinite" type, i.e. the process of type derivation never stops.

Pair equality on components

I would like to define a function of the following type
pairEquality :
(a, b : (obj1, obj2))
-> (fst a) = (fst b)
-> (snd a) = (snd b)
-> a = b
but I am a bit at loss with the implementation.
I know I can write
pairEquality' :
a1 = b1
-> a2 = b2
-> (a1, a2) = (b1, b2)
but that doesn't seem to compile where I need to use it (that's another question: what's the big difference between the two functions?)
The first implementation is pretty straight-forward. Once you split the tuples to get pairEquality (a, b) (x, y) prf1 prf2 = ?t and inspect the the hole, you already see, that the compiler infers that prf1 : a = x, prf2: b = y, alas:
pairEquality :
(a, b : (obj1, obj2))
-> (fst a) = (fst b)
-> (snd a) = (snd b)
-> a = b
pairEquality (x, y) (x, y) Refl Refl = Refl
In pairEquality you de-construct the tuples and in pairEquality' you construct the tuples. Latter is usually a better approach, and I guess you can change something in your caller function so it can be used.
I actually find out I can define pairEquality in terms of pairEquality' as
pairEquality :
(a, b : (obj1, obj2))
-> (fst a) = (fst b)
-> (snd a) = (snd b)
-> a = b
pairEquality (a1, a2) (b1, b2) = pairEquality' {a1} {a2} {b1} {b2}

What is the equivalent of propositional not equals?

I somewhat recently asked a question and resolved the issue with a some applications of the rewrite tactic. I then decided to look back at one of my other questions on code review asking for a review of my attempt to formalize Hilbert's (based on Euclid's) geometry.
From the first question, I learned there is a distinction between propositional equality and boolean equality and propositional equality. Looking back at the some of the axioms I wrote for the Hilbert plane, I utilized boolean equality extensively. Although I am not 100% sure, in light of the answer I received, I suspect that I don't want to use boolean equality.
For instance, take this axiom:
-- There exists 3 non-colinear points.
three_non_colinear_pts : (a : point ** b : point ** c : point **
(colinear a b c = False,
(a /= b) = True,
(b /= c) = True,
(a /= c) = True))
I tried rewriting it to not involve the = True:
-- There exists 3 non-colinear points.
three_non_colinear_pts : (a : point ** b : point ** c : point **
(colinear a b c = False,
(a /= b),
(b /= c),
(a /= c)))
All in all I took the code from my question on codereview removed the == and removed = True:
interface Plane line point where
-- Abstract notion for saying three points lie on the same line.
colinear : point -> point -> point -> Bool
coplanar : point -> point -> point -> Bool
contains : line -> point -> Bool
-- Intersection between two lines
intersects_at : line -> line -> point -> Bool
-- If two lines l and m contain a point a, they intersect at that point.
intersection_criterion : (l : line) ->
(m : line) ->
(a : point) ->
(contains l a = True) ->
(contains m a = True) ->
(intersects_at l m a = True)
-- If l and m intersect at a point a, then they both contain a.
intersection_result : (l : line) ->
(m : line) ->
(a : point) ->
(intersects_at l m a = True) ->
(contains l a = True, contains m a = True)
-- For any two distinct points there is a line that contains them.
line_contains_two_points : (a :point) ->
(b : point) ->
(a /= b) ->
(l : line ** (contains l a = True, contains l b = True ))
-- If two points are contained by l and m then l = m
two_pts_define_line : (l : line) ->
(m : line) ->
(a : point) ->
(b : point) ->
(a /= b) ->
contains l a = True ->
contains l b = True ->
contains m a = True ->
contains m b = True ->
(l = m)
same_line_same_pts : (l : line) ->
(m : line) ->
(a : point) ->
(b : point) ->
(l /= m) ->
contains l a = True ->
contains l b = True ->
contains m a = True ->
contains m b = True ->
(a = b)
-- There exists 3 non-colinear points.
three_non_colinear_pts : (a : point ** b : point ** c : point **
(colinear a b c = False,
(a /= b),
(b /= c),
(a /= c)))
-- Any line contains at least two points.
contain_two_pts : (l : line) ->
(a : point ** b : point **
(contains l a = True, contains l b = True))
-- If two lines intersect at a point and they are not identical, that is the o-
-- nly point they intersect at.
intersect_at_most_one_point : Plane line point =>
(l : line) -> (m : line) -> (a : point) -> (b : point) ->
(l /= m) ->
(intersects_at l m a = True) ->
(intersects_at l m b = True) ->
(a = b)
intersect_at_most_one_point l m a b l_not_m int_at_a int_at_b =
same_line_same_pts
l
m
a
b
l_not_m
(fst (intersection_result l m a int_at_a))
(fst (intersection_result l m b int_at_b))
(snd (intersection_result l m a int_at_a))
(snd (intersection_result l m b int_at_b))
This gives the error:
|
1 | interface Plane line point where
| ~~~~~~~~~~~~~~~~
When checking type of Main.line_contains_two_points:
Type mismatch between
Bool (Type of _ /= _)
and
Type (Expected type)
/home/dair/scratch/hilbert.idr:68:29:
|
68 | intersect_at_most_one_point : Plane line point =>
| ^
When checking type of Main.intersect_at_most_one_point:
No such variable Plane
So, it seems that /= works only for boolean. I have been unable to find a "propositional" /= like:
data (/=) : a -> b -> Type where
Does a propositional not equals exist? Or am I wrong about wanting to change from boolean to propositional equality?
The propositional equivalent to the boolean a /= b would be a = b -> Void. Void is a type with no constructors. So whenever you have a contra : Void, something has gone wrong. So a = b -> Void is to understand as: if you have an a = b, there is a contradiction. Usually written as Not (a = b), which is just a shorthand (Not a = a -> Void).
You're right to change to propositional equality. You might even change your boolean properties like contains : line -> point -> Bool to Contains : line -> point -> Type. Subsequently contains l p = True to Contains l p, and contains l p = False to Not (Contains l p).
That's a case of boolean blindness, i.e. with prf : contains l p = True, the only thing we know is that contains l p is True (and the compiler would need to take a look at contains to guess why it is True). On the other hand, with prf : Contains l p you have a constructed proof prf why the proposition Contains l p holds.

Simplifying a two-parameter anonymous function in Elm

In Elm, if I have an anonymous function
(\f x -> f x)
I can simplify it to
(<|)
Can the same be done for a two-parameter function where the parameters are arguments to another function?
(\x y -> f x y |> g)
I thought I could simply use
(f |> g)
but the compiler complains about the types.
Specifically, in one of the cases for my update function, I have something like this:
let
msgNames = [Foo, Bar]
values = ["f", "b"] // These values are actually derived
// by a more complicated operation
model_ = List.map2 (<|) msgNames values
|> List.foldl (\msg mod -> update msg mod |> Tuple.first)
model
in
( model_, Cmd.none )
I am trying to simplify the anonymous function argument to List.foldl to something like (update |> Tuple.first), but I get the following error from the compiler:
The right side of (|>) is causing a type mismatch.
159| update |> Tuple.first)
^^^^^^^^^^^
(|>) is expecting the right side to be a:
(Msg -> Model -> ( Model, Cmd Msg )) -> a
But the right side is:
(( Model, Cmd Msg )) -> Model
We can follow a few steps to simplify:
(\x y -> f x y |> g)
... can be written as
(\x y -> g (f x y))
... can be written as
(\x -> g << f x)
One more step and things get a little more confusing:
(((<<) g) << f)
This matches what you get from pointfree.io (which is Haskell where function composition is done using the . operator):
(g .) . f
If you are trying to improve readability, you might just want to make your own infix function:
infixr 9 <<<
(<<<) : (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(<<<) g f x y =
g (f x y)
And now you can use it like this:
(g <<< f)

Finding and replacing

There are times that we want to find an element in a list with a function a -> Bool and replace it using a function a -> a, this may result in a new list:
findr :: (a -> Bool) -> (a -> a) -> [a] -> Maybe [a]
findr _ _ [] = Nothing
findr p f (x:xs)
| p x = Just (f x : xs)
| otherwise = case findr p f xs of Just xs -> Just (x:xs)
_ -> Nothing
Is there any function in the main modules which is similar to this?
Edit: #gallais points out below that you end up only changing the first instance; I thought you were changing every instance.
This is done with break :: (a -> Bool) -> [a] -> ([a], [a]) which gives you the longest prefix which does not satisfy the predicate, followed by the rest of the list.
findr p f list = case break p list of
(xs, y : ys) -> Just (xs ++ f y : ys)
(_, []) -> Nothing
This function is, of course, map, as long as you can combine your predicate function and replacement function the right way.
findr check_f replace_f xs = map (replace_if_needed check_f replace_f) xs
replace_if_needed :: (a -> Bool) -> (a -> a) -> (a -> a)
replace_if_needed check_f replace_f = \x -> if check_f x then replace_f x else x
Now you can do things like findr isAplha toUpper "a123-bc".