Is there an ASCII alias for the function composition operator in Julia, ∘?
In general, is there a way to find ASCII/Unicode variants of operators?
julia> ∘
∘ (generic function with 2 methods)
^Tried this, ≈ for example has an alternative:
julia> ≈
isapprox (generic function with 8 methods)
For ∘ there is no alternative AFAICT. You can check by running:
julia> methods(∘)
# 3 methods for generic function "∘":
[1] ∘(f) in Base at operators.jl:874
[2] ∘(f, g) in Base at operators.jl:875
[3] ∘(f, g, h...) in Base at operators.jl:876
and opening the respective function definition (if you have a properly configured Julia installation just press e.g. 1 and then CTRL-Q) to get:
function ∘ end
∘(f) = f
∘(f, g) = (x...)->f(g(x...))
∘(f, g, h...) = ∘(f ∘ g, h...)
However, it is easy enough just to write:
const compose = ∘
and now you can use compose(f, g) instead of f ∘ g.
For ≈ and isapprox it is the case that in the code isapprox function is defined and then:
const ≈ = isapprox
definition is added in floatfuncs.jl.
Related
I´m trying to learn more about dependent types using IDRIS.
The example I am trying to emulate uses composition of Vectors.
I understand Functor and Applicative implementations for Vectors but I am struggling to implement them for the Composition.
data Vector : Nat -> Type -> Type where
Nil : Vector Z a
(::) : a -> Vector n a -> Vector (S n) a
Functor (Vector n) where
map f [] = []
map f (x::xs) = f x :: map f xs
Applicative (Vector n) where
pure = replicate _
fs <*> vs = zipWith apply fs vs
Now the Composition and Decomposition-Function look like this:
data (:++) : (b -> c) -> (a -> b) -> a -> Type where
Comp : (f . g) x -> (f :++ g) x
unComp : (f :++ g) a -> (f . g) a
unComp (Comp a) = a
User with Vectors it encapsulates a Vector of Vectors.
Now I need an Applicative for the Composition (Vector n) :++ (Vector n).
I can´t even get Functor to work and am mainly trying to see what I´m doing wrong. I tried the following and, since Functor is already implemented for Vectors, that this would work
Functor ((Vector n) :++ (Vector n)) where
map f (Comp []) = Comp []
map f (Comp (x::xs)) = Comp ((f x) :: (map f (Comp xs)))
but the Compiler gives an Error-Message:
When checking an application of constructor Main.:::
Unifying a and Vector (S n) a would lead to infinite value
Isn´t unifying and element of type a and a Vector n a exactly the purpose of (::)?
I am obviously doing something wrong and I can´t get this to work. I also have the feeling it´s probably easy to solve, but after hours of reading and trying I still don´t get it.
If someone could give me advice or explain to me how the Functor and Applicative implementations could look like, I would be very grateful.
Update: Idris 2 now has this builtin. Functor for Compose, Applicative for Compose
I think you can implement a general instance of Functor and Applicative like with Haskell's Compose.
newtype Compose f g a = Compose { getCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
a <$ (Compose x) = Compose (fmap (a <$) x)
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose (liftA2 (<*>) f x)
liftA2 f (Compose x) (Compose y) =
Compose (liftA2 (liftA2 f) x y)
To answer your specific question (but don't do it this way):
Functor ((Vector n) :++ (Vector n)) where
map f (Comp x) = Comp $ map (map f) x
I am a student of functional programming, sorry if my question sounds weird--I am trying to wrap my mind around the given type signatures for functions and how they are implemented.
Looking at the signature for ap (Substitution)
https://gist.github.com/Avaq/1f0636ec5c8d6aed2e45
(a → b → c) → (a → b) → a → c
Is given here as
const S = f => g => x => f(x)(g(x));
Which I think I understand. f is a function that takes two parameters, a and b and returns c. g is a function that takes a and returns b. So g(a) returns b and therefore f(a)(b) can be written as f(a)(g(a)), which returns c.
g(a) is the substitute for b ?
Ok now I'm looking at a different implementation that still makes sense:
https://github.com/sanctuary-js/sanctuary-type-classes/tree/v7.1.1#ap--applyf--fa-bfa---fb
ap(Identity(Math.sqrt), Identity(64))
The type signature
(f (a -> b), f a) -> f b
Seem similar to
(a → b → c) → (a → b) → a → c
Re-writing the second using a = f, b = a, and c = b I get
(f -> a -> b) -> (f -> a) -> f -> b
Presuming that ap takes two parameters, where in the first f could be some functor that contains a function a -> b and in the second f some functor that contains a returning a functor that substitutes the first functor's function with the end point b given then functor containing a.
Okay, stepping back, these two things looks vastly different and I can't wrap my mind around how they are somehow saying the same thing.
const S = f => g => x => f(x)(g(x))
ap(Identity(Math.sqrt), Identity(64))
From my understanding, ap(F(g),F(a)) can be express as F(a).map(g) which, again, I still have a hard time equating to const S = f => g => x => f(x)(g(x)). Perhaps I'm misunderstanding something.
...maybe my misunderstanding has to do with the expression of ap and how that correlates to f => g => x => f(x)(g(x)) because I can see how they both express the same signature but I don't see them as the same thing.
Anyone who can lend some cognitive assistance here, I would greatly appreciate it
ap is the name for a transformation that behaves the same way on a large number of container types known as Applicative Functors. One such container type is the Function: it can be treated as a container of its return value.
The S combinator you found in my gist comes from the untyped Lambda Calculus and is a transformation of a Function specifically. It happens to also be a valid implementation of Applicative Functor for Function, and it happens to be the implementation of choice for both Ramda and Sanctuary. This is why you can use ap as S.
To gain an understanding of how ap is S, let's have a look at the signature for ap:
Apply f => (f (a -> b), f a) -> f b
And let's get rid of the comma by currying the function. This should make the next steps a little easier to follow:
Apply f => f (a -> b) -> f a -> f b
The Apply f part shows that, where ever we see f a, we can use an Applicative Functor container that contains a. Let's specialise this signature for the Function container, by replacing f with (Function x). x is the input to the function, and what follows is the output.
(Function x) (a -> b) -> (Function x) a -> (Function x) b
This reads as: Given a Function from x to a Function from a to b, and a Function from x to a, returns a Function from x to b.
We can remove the brackets around Function x, because of the way constructor associativity works:
Function x (a -> b) -> Function x a -> Function x b
And another way to write Function a b is using the arrow notation: (a -> b), so in the next step we do just that:
(x -> (a -> b)) -> (x -> a) -> (x -> b)
And finally we can get rid of the additional brackets again, and find that it's our S combinator:
(x -> a -> b) -> (x -> a) -> x -> b
(a -> b -> c) -> (a -> b) -> a -> c
First of all, I think there is no easy explanation of why the applicative functor for the function type in untyped lambda calculus is called substitution. AFAIK, Schönfinkel originally called this combinator fusing or amalgamation function.
In order to specialize the general applicative functor type (f (a -> b), f a) -> f b (uncurried form), we need to know what the parameterized type variable f exactly represents in the context of the function type.
As every functor applicative functors are parameterized over a single type. The function type constructor, however, needs two types - one for the argument and another for the return value. For functions to be an instance of (applicative) functors, we must therefore ignore the type of the return value. Consequently, f represents (a -> ), ie. the function type itself and the type of its argument. The correct notation for the partially applied function type constructor is actually prefix (->) a, so let's stick to this.
Next, I'm gonna rewrite the general applicative type in curried form and substitute f with (->) r. I use another letter to delimit the type parameter of the applicative from other type variables:
(f (a -> b), f a) -> f b
f (a -> b) -> f a -> f b // curried form
// substitution
(->) r (a -> b) -> (->) r a -> (->) r b // prefix notation
(r -> a -> b) -> (r -> a) -> (r -> b) // infix notation
// omit unnecessary parenthesis
(r -> a -> b) -> (r -> a) -> r -> b
This is exactly the type of the S combinator.
How do you make an anonymous recursive function (something simple for example factorial n?) I have heard it is possible but no idea how to make it work in OCaml.
let a =
fun x -> ....
I just don't know how to keep it going...
Here is a definition of factorial using only anonymous functions:
let fact =
(fun f -> (fun x a -> f (x x) a) (fun x a -> f (x x) a))
(fun f n -> if n < 2 then 1 else n * f (n - 1))
It requires the use of the -rectypes flag.
Here's a session showing that it works:
$ rlwrap ocaml -rectypes
OCaml version 4.03.0
let fact =
(fun f -> (fun x a -> f (x x) a) (fun x a -> f (x x) a))
(fun f n -> if n < 2 then 1 else n * f (n - 1));;
val fact : int -> int = <fun>
# fact 8;;
- : int = 40320
I cheated somewhat by looking up the Y Combinator here: Rosetta Code: Y Combinator
Update
Disclaimer: you would do better to read up on lambda calculus, fixed points, and the Y Combinator than to get your info from me. I'm not a theorist, just a humble practitioner.
Following the actual computation is almost impossible (but definitely worth doing I'm sure). But at a high level the ideas are like this.
The first line of the definition is the Y Combinator, which in general calculates the fixed point of a function. It so happens that a recursive function is the fixed point of a function from functions to functions.
So the first goal is to find the function whose fixed point is the factorial function. That's the second line of the definition. If you give it a function of type int -> int, it gives you back another function of type int -> int. And if you give it the factorial function, it gives you back the factorial function. This means that the factorial function is its fixed point.
So then when you apply the Y Combinator to this function, you do indeed get the factorial function.
Let me try to expand a bit on Jeffrey Scofield's answer. A non-anonymous recursive definition of the factorial function could be
let rec fact n =
if n < 2 then 1 else n * fact (n - 1)
The first problem you encounter when you try to define an anonymous recursive function is how to do the actual recursive call (fact (n - 1) in our case). For a call we need a name and we do not have a name for an anonymous function. The solution is to use a temporary name. With the temporary name f, the definition body is just
fun n -> if n < 2 then 1 else n * f (n - 1)
This term does not have a type, because the "temporary name" f is unbound. But we can turn it into a value that does have a type by bounding f as well. Let us call the result g:
let g = fun f n -> if n < 2 then 1 else n * f (n - 1)
g is not yet anonymous at the moment, but only because I want to refer to it again.
Observe that g has type (int -> int) -> (int -> int). What we want (the factorial function) will have type (int -> int). So g takes something of the type we want (a function type in this case) and produces something of the same type. The intuition is that g takes an approximation of the factorial function, namely a function f which works for all n up to some limit N and returns a better approximation, namely a function that works for all n up to N+1.
Finally we need something that turns g into an actual recursive definition.
Doing so is a very generic task. Recall that g improves the approximation quality. The final factorial function fact is one which cannot be further improved. So applying g to fact should be the same as just fact. (Actually that is only true from a value point of view. The actual computation inherent in g fact n for some n is different from that of just fact n. But the returned values are the same.) In other words, fact is a fixed point of g. So what we need is something that computes fixed points.
Luckily, there is a single function that does so: The Y combinator. From a value point of view, the Y combinator (let us use y in OCaml, as uppercase is reserved for constructors) is defined by the fact that y g = g (y g) for all g: given some function g, the combinator returns one of its fixed points.
Consequently,
y : (`a -> `a) -> `a
In our case the type variable is instantiated by (int -> int).
One possible way to define y would be
let y = fun g -> (fun x -> g (x x)) (fun x -> g (x x))
but this works only with lazy evaluation (as, I believe, Haskell has). As OCaml has eager evaluation, it produces a stack overflow when used. The reason is that OCaml tries to turn something like y g 8 into
g (y g) 8
g (g (y g)) 8
g (g (g (y g))) 8
...
without ever getting to call g.
The solution is to use deferred computation inside of y:
let y = fun g -> (fun x a -> g (x x) a) (fun x a -> g (x x) a)
One drawback is that y does not work for arbitrary types any more. It only works for function types.
y : ((`b -> `c) -> (`b -> `c)) -> (`b -> `c)
But you asked for recursive definitions of functions anyway, not for recursive definitions of other values. So, our definition of the factorial function is y g with y and g defined as above. Neither y nor g are anonymous yet, but that can be remedied easily:
(fun g -> (fun x a -> g (x x) a) (fun x a -> g (x x) a))
(fun f n -> if n < 2 then 1 else n * f (n - 1))
UPDATE:
Defining y only works with the -rectypes option. The reason is that we apply x to itself.
There is also an "intuitive" way to accomplish anonymous recursion without resorting to Y combinators.
It makes use of a let binding to store the value of a lambda that accepts itself as an argument, so that it can call itself with itself as the first parameter, like so:
let fact = (let fact0 = (fun self n -> if n < 2 then 1 else n * self self (n - 1)) in (fun n -> fact0 fact0 n));;
It's anonymous only to the extent that it is not defined with let rec.
I'd like to change the priority of ∘ so that it is applied first. Hence no bracket is needed in the function composition below. Is this possible?
julia> ∘(f,g) = x->f(g(x))
∘ (generic function with 1 method)
julia> (sqrt ∘ abs)(randn())
0.9069709279812338
julia> sqrt ∘ abs(randn())
(::#15) (generic function with 1 method)
Julia is strong at metaprogramming so you have to be able to make your own microlanguage.
I am just beginner at Julia so code below is just my little experiment! (And it is inclomplete because problems with parsing multiple lines )
But maybe it could be inspirational:
module M
macro x(a)
w = r"(\w+)\s*∘\s*(\w+)" # trying to find words around ∘
s = s"(\1 ∘ \2)" # and enclosed them into brackets
b = replace("$a", w, s)
return :(eval(parse($b)))
end
end
import M
M.#x(
sqrt ∘ abs(randn())
)
From categorical point of view, functor is pair of two maps (one between objects and another between arrows of categories), following some axioms.
I have assumed, what every Functor instance is similar to mathematical definition i.e. can map both objects and functions, but Haskell's Functor class has only function fmap which maps functions.
Why so?
UPD In other words:
Every Monad type M has an function return :: a -> M a.
And Functor type F has no function return :: a -> F a, but only F x constructor.
There are two levels: types and values. As objects of Hask are types, you can map them only with type constructors, which have the * -> * kind:
α -> F α (for Functor F),
β -> M β (for Monad M).
Then for a functor you need a map on morphisms (i.e. functions, which are values):
fmap :: (α -> β) -> (F α -> F β)
The important thing is that return :: α -> M α of Monad is not a mapper of a type α to the M α as you might think. According to the mathematical definition of a monad, return corresponds to a natural transformation from Id functor to the M functor. And the Id functor is kind of implicit in Hask. The standard definition of a monad also requires another natural transformation M ◦ M -> M. So translating it to Haskell would look like
class Functor m => Monad m where
return :: Id α -> m α
join :: m (m α) -> m α
(As a side-note: these two natural transformations are actually the unit and multiplication, which make monad a monoid in the category of endofunctors)
The actual definition differs, but is equivalent. See Haskell/wiki on that.
If you take the composition-like operator derived from the standard bind >>= :: m α -> (α -> m β) -> m β:
(>=>) :: Monad m => (α -> m β) -> (β -> m γ) -> (α -> m γ)
f >=> g = \a => f a >>= g
You can see, that it's all actually about the Kleisli category. See also the article on nLab about monads in computer science.
Objects of a category are not the same as objects in a OO programming language (we prefer to call those values in Haskell; what they mean in category theory was discussed here). Rather, the objects of Hask are types. Haskell Functors are endofunctors in Hask, i.e. associate types to types, by the following means:
Prelude> :k Maybe
Maybe :: * -> *
Prelude> :k Int
Int :: *
Prelude> :k Maybe Int
Maybe Int :: *
OTOH, the arrows of Hask are in fact values, of some function type a -> b. These are associated in the following way:
fmap :: ( Functor (f :: t -> f t {- type-level -} ) )
=> (a->b) -> fmap(a->b) {- value-level -}
≡ (a->b) -> (f a->f b)
Though you were using those fancy categorical terms in your question and should be completely satisfied with the existing answers, here is an attempt for a rather trivial explanation:
Suppose there would be a function return (or pure or unit or ...) in the Functor type class.
Now try to define some common instances of Functor: [] (Lists), Maybe, ((,) a) (Tuples with a left component)
Easy enough, eh?
Here are the ordinary Functor instances:
instance Functor [] where
fmap f (x : xs) = f x : fmap xs
fmap _ [] = []
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap _ Nothing = Nothing
instance Functor ((,) a) where
fmap f (x, y) = (x, f y)
What about return for Functor now?
Lists:
instance Functor [] where
return x = [x]
Alright. What about Maybe?
instance Functor Maybe where
return x = Just x
Okay. Now Tuples:
instance Functor ((,) a) where
return x = (??? , x)
You see, it is unknown which value should be filled into the left component of that tuple. The instance declaration says it has a type a but we do not know a value from that type. Maybe the type a is the Unit type with only one value. But if its Bool, should we take True or False? If it is Either Int Bool should we take Left 0 or Right False or Left 1?
So you see, if you had a return on Functors, you could not define a lot of valid functor instances in general (You would need to impose a constraint of something like a FunctorEmpty type class).
If you look at the documentation for Functor and Monad you will see that there are indeed instances for Functor ((,) a) but not for Monad ((,) a). This is because you just can't define return for that thing.
If you have
instance Functor F where
fmap = ...
Then the type constructor F is the action on objects (which are types) taking a type T to the type F T, and fmap is the action on morphisms (which are functions) taking a function f :: T -> U to fmap f :: F T -> F U.
In category theory, a functor maps all the objects from a category to another, but a functor doesn't map the elements in the objects.