J is a fantastic programming language that I have decided to learn. As a simple exercise, I decided to emulate a range. There is a builtin function i. that creates a range 0..i-1. Using some math, I have that this is the range between a and b:
a + i. (b - a - 1)
Success! I thought. Now, the "simple" task of converting to a verb is set before me. This is my problem now. I have a (the left argument) being called on both sides of the verb +. I thought of using evoke, but I am not sure as how to make it work.
So my question stands: How do I convert an expression of the form a f (a g b) or, more specifically, a f (a g b h c) (and similar forms) to a pure verb? I don't want to use explicit arguments, for what's the fun in that? ;)
EDIT My solution is as thus:
range =: [(+i.)>:#-~
To convert an expression of the form x f (x g y) to a form of x h y you can use a dyadic fork:
x (F G H) y = (x F y) G (x H y)
and the identity verb: x [ y = x, making:
x ([ f g) y = (x [ y) f (x g y) = x f (x g y)
So the verb you are looking for is h =: [ f g
Related
I have given a task to make the Integer-List Generator [m...] in lambda calculus.
So it should fullfill this definition.
Y F m ≡ : m (Y F (+ m 1))
Therefor a lambda calculus F is needed.
I don't know how to find which lambda calculus F should be.
Does anyone have any suggestions for F?
Equational reasoning gets you where you need to go. We have these two equations:
Y F = F (Y F) -- the basic useful property of Y
Y F m = : m (Y F (+ m 1))
So now we just solve. We replace the Y F in Y F m = ... with the thing it's equal to:
F (Y F) m = : m (Y F (+ m 1))
One solution to this equation is to generalize from Y F to an arbitrary variable g everywhere:
F g m = : m (g (+ m 1))
Done. This is now a fine defining equation for F. If you don't like the syntax sugar, you could instead write it as a lambda:
F = \g m -> : m (g (+ m 1))
Of course, when you practice this yourself on other problems, be kind to yourself: there are lots of different choices of how to rewrite things at each step, and you might have to play with a couple different ways before you stumble on one that gets you where you want to go, rather than following such a straight-line path as I've outlined here where I had already tried and eliminated a bunch of wrong ways. Persevere, and you can learn to do it.
I would like to provide some notes on the relationship of [m..] and y f m = m : (y f (+ m 1)). Starting with the observation
[m..] = m : [m+1..]
and replacing [m..] using g m = [m..], we arrive at
g m = m : (g (m+1))
Taken as a definition of g, observe that this is a recursive definition. Recursive definitions can be split into a generic recursive part y (given by y f = f (y f)) and a non-recursive part f
g = y f
This replaces the recursive g by the non-recursive f which we still have to determine/solve for. Substituting g in the previous equation gives
y f m = m : (y f (m+1))
The take away message is that a recursive function (g) can be refactored into a non-recursive function (f). All you need is a single recursive function (y) which you can reuse for other recursive functions/problems.
Diving into Haskell, and while I am enjoying the language I'm finding the pointfree style completely illegible. I've come a across this function which only consists of these ASCII boobies as seen below.
f = (.)(.)
And while I understand its type signature and what it does, I can't for the life of me understand why it does it. So could someone please write out the de-pointfreed version of it for me, and maybe step by step work back to the pointfree version sorta like this:
f g x y = (g x) + y
f g x = (+) (g x)
f g = (+) . g
f = (.) (+)
Generally (?) (where ? stands for an arbitrary infix operator) is the same as \x y -> x ? y. So we can rewrite f as:
f = (\a b -> a . b) (\c d -> c . d)
Now if we apply the argument to the function, we get:
f = (\b -> (\c d -> c . d) . b)
Now b is just an argument to f, so we can rewrite this as:
f b = (\c d -> c . d) . b
The definition of . is f . g = \x -> f (g x). If replace the outer . with its definition, we get:
f b = \x -> (\c d -> c . d) (b x)
Again we can turn x into a regular parameter:
f b x = (\c d -> c . d) (b x)
Now let's replace the other .:
f b x = (\c d y -> c (d y)) (b x)
Now let's apply the argument:
f b x = \d y -> (b x) (d y)
Now let's move the parameters again:
f b x d y = (b x) (d y)
Done.
You can also gradually append arguments to f:
f = ((.) . )
f x = (.) . x
f x y = ((.) . x) y
= (.) (x y)
= ((x y) . )
f x y z = (x y) . z
f x y z t = ((x y) . z) t
= (x y) (z t)
= x y (z t)
= x y $ z t
The result reveals that x and z are actually (binary and unary, respectively) functions, so I'll use different identifiers:
f g x h y = g x (h y)
We can work backwards by "pattern matching" over the combinators' definitions. Given
f a b c d = a b (c d)
= (a b) (c d)
we proceed
= B (a b) c d
= B B a b c d -- writing B for (.)
so by eta-contraction
f = B B
because
a (b c) = B a b c -- bidirectional equation
by definition. Haskell's (.) is actually the B combinator (see BCKW combinators).
edit: Potentially, many combinators can match the same code. That's why there are many possible combinatory encodings for the same piece of code. For example, (ab)(cd) = (ab)(I(cd)) is a valid transformation, which might lead to some other combinator definition matching that. Choosing the "most appropriate" one is an art (or a search in a search space with somewhat high branching factor).
That's about going backwards, as you asked. But if you want to go "forward", personally, I like the combinatory approach much better over the lambda notation fidgeting. I would even just write many arguments right away, and get rid of the extra ones in the end:
BBabcdefg = B(ab)cdefg = (ab)(cd)efg
hence,
BBabcd = B(ab)cd = (ab)(cd)
is all there is to it.
I have many methods that have boilerplate code in their definition, look at the example above.
replace:: Term -> Term -> Formula -> Formula
replace x y (Not f) = Not $ replace x y f
replace x y (And f g) = And (replace x y f) (replace x y g)
replace x y (Or f g) = Or (replace x y f) (replace x y g)
replace x y (Biimp f g) = Biimp (replace x y f) (replace x y g)
replace x y (Imp f g) = Imp (replace x y f) (replace x y g)
replace x y (Forall z f) = Forall z (replace x y f)
replace x y (Exists z f) = Exists z (replace x y f)
replace x y (Pred idx ts) = Pred idx (replace_ x y ts)
As you can see, the definitions for replace function follows a pattern. I want to have the same behavior of the function, simplifying his definition, probably using some pattern matching, maybe with a wildcard _ or X over the arguments, something like:
replace x y (X f g) = X (replace x y f) (replace x y g)
For avoiding the following definitions:
replace x y (And f g) = And (replace x y f) (replace x y g)
replace x y (Or f g) = Or (replace x y f) (replace x y g)
replace x y (Biimp f g) = Biimp (replace x y f) (replace x y g)
replace x y (Imp f g) = Imp (replace x y f) (replace x y g)
Is there some way? Forget about the purpose of the function, it could be whatever.
If you have many constructors that should be treated in a uniform way, you should make your data type reflect that.
data BinOp = BinAnd | BinOr | BinBiimp | BinImp
data Quantifier = QForall | QExists
data Formula = Not Formula
| Binary BinOp Formula Formula -- key change here
| Quantified Quantifier Formula
| Pred Index [Formula]
Now the pattern match for all binary operators is much easier:
replace x y (Binary op f g) = Binary op (replace x y f) (replace x y g)
To preserve existing code, you can turn on PatternSynonyms and define the old versions of And, Or, and so on back into existence:
pattern And x y = Binary BinAnd x y
pattern Forall f = Quantified QForall f
I'm not entirely sure this is what you are looking for but you could do the following. The idea is that you can consider a formula to be abstracted over another type (usually a Term in your case). Then, you can define what it means to map over a formula. I tried to replicate your data definitions, although I have some problems with Formula - namely that all the constructors seem to require another Formula...
{-# LANGUAGE DeriveFunctor #-}
data Formula a
= Not (Formula a)
| And (Formula a) (Formula a)
| Or (Formula a) (Formula a)
| Biimp (Formula a) (Formula a)
| Imp (Formula a) (Formula a)
| Forall a (Formula a)
| Exists a (Formula a)
| Pred a (Formula a)
deriving (Functor)
data Term = Term String {- However you define it, doesn't matter -} deriving (Eq)
replace :: (Functor f, Eq a) => a -> a -> f a -> f a
replace x y = fmap (\z -> if x == z then y else z)
The interesting thing to note is that now the replace function can be applied to anything that is a functor - it even serves as replace for a list!
replace 3 9 [1..6] = [1,2,9,4,5,6]
EDIT As an afterthought, if you are implementing a substitution style replace where terms in formulas can be shadowed (the usual scoping rules), you will probably end up doing something like this:
replace' :: (Eq a) => a -> a -> Formula a -> Formula a
replace' x y f#(Forall z _) | x == z = f
replace' x y f#(Exists z _) | x == z = f
replace' x y f#(Pred z _) | x == z = f
replace' x y formula = fmap (replace' x y) formula
Which isn't as cute, but also isn't as straightforward pf a problem.
Data.Functor.Foldable abstracts the pattern of recursive data structures:
import Data.Functor.Foldable
data FormulaF t
= Not t
| And t t
| Or t t
| Biimp t t
| Imp t t
| Forall A t
| Exists A t
| Pred B C
deriving (Functor, Foldable, Traversable)
type Formula = Fix FormulaF
replace :: Term -> Term -> Formula -> Formula
replace x y = cata $ \case ->
Pred idx ts -> Pred idx (replace_ x y ts)
f -> f
By the way, beware of replace x y (Forall x (f x)) = Forall x (f y): Substitution is the process of replacing all free occurences of a variable in an expression with an expression.
I must find a function G which has a fixed point, and this fixed point must be the Y combinator.
Recall that Y F = F(Y F) for all F. I want a function G such that G Y = Y.
How to write such a function in in Haskell?
Let
g w = \f -> f (w f)
Then, if
y f = f (y f)
we have
g y
-- definition of g
= \f -> f (y f)
-- property of y
= \f -> y f
-- eta-conversion
= y
Hence, y is a fixed point of g.
More than that: the set of fixed points of g is precisely the set of fixed point combinators. This is because above we did not exploit the definition of y, but merely the fact that it is a fixed point combinator.
Note that y is also a fixed point of id (anything is a fixed point of id)
and of const y (as #DanielWagner writes in his answer).
For all values v, the function const v has (unique, and therefore also least) fixed-point v.
Daniel's answer is very good, but I'd like to add the other extreme. Everything is a fixed point of the identity function. Thus, take G to be
\x -> x
indeed:
GY = (\x -> x)Y = Y
In programming language J, is a train of verbs always associative? If it is, Are there any proofs?
No, a train of verbs is not associative and this follows the definitions. For example, a fork is
(f g h) y = (f y) g (h y)
but
(f (g h)) y = y f ((g h) y) = y f (y g (h y))
which can also be written as y f y g h y. And
((f g) h) y = y (f g) (h y) = y f (g (h y))
which can also be written as y f g h y.
Those three are completely different things.
Train in J is right associative, and the minimum group is a fork. Only when it cannot make a fork, it makes a hook. So
vvvvv = (vv(vvv)),
And
vvvv= (v(vvv)).