> S.reduce(S.flip(S.K),[],S.Left([1,2]))
[]
> S.reduce(S.flip(S.K),[],S.Right([1,2]))
[ 1, 2 ]
I was trying to understand sanctuary and its working can anybody explain the above outcomes in detail
In my understanding S.reduce takes a mapping function and uses the input array which should be of type either and reduces it
But why its empty array in first case and same array in second case
Let's start with a more familiar example: using S.reduce on an array.
> S.reduce (acc => s => acc + s) ('initial:') (['foo', 'bar', 'baz'])
'initial:foobarbaz'
Now, let's specialize the type of S.reduce to explain the behaviour above.
S.reduce :: Foldable f => (b -> a -> b) -> b -> f a -> b
-- replace ‘Foldable f => f’ with ‘Array’ --
S.reduce :: (b -> a -> b) -> b -> Array a -> b
Next, let's specialize the type of S.reduce to see how it will operate on Either values.
S.reduce :: Foldable f => (b -> a -> b) -> b -> f a -> b
-- replace ‘Foldable f => f’ with ‘Either x’ --
S.reduce :: (b -> a -> b) -> b -> Either x a -> b
What can we do when given S.Left ('foo') as the Either x a? We have an x ('foo') but no a. Because we don't have an a we cannot make use of the b -> a -> b function. Thus, the only b we can possibly return is the initial value.
> S.reduce (acc => s => acc + s) ('initial:') (S.Left ('foo'))
'initial:'
What can we do when given S.Right ('bar') as the Either x a? We have an a, which we could feed to the b -> a -> b function along with the initial value to produce another value of type b.
> S.reduce (acc => s => acc + s) ('initial:') (S.Right ('bar'))
'initial:bar'
If S.reduce were to return 'initial:' or 'initial:bar:bar:bar' in the case above it would still be conforming to the type signature, but the fantasy-land/reduce implementation for Sanctuary's Either type applies the function exactly once when given a Right.
Related
I am very new to Haskell and I wrote a Data Type in Haskell
for representing an interval map.
What does that mean? Briefly: A map data type that gives you a value back
for every possible key (put simply in my case [0..]).
Then you insert "sequences" like I want my map to hold from 7 to 23 'b'
so keys 0 to 6 will be init value e.g. 'a' and 7 to 23 will be 'b' and 24 and ongoing will be 'a' again etc.
I managed to wrote the Data Type, a get and insert function as well as a
functor version.
But I can't managed to get a applicative functor version to work.
The idea is to set the keys value to [0..] and just work on the values.
Here is my code and thanks for any provided help!
-- Building an interval map data structure in haskell
data IntervalMap k v = IntervalMap {keys :: [k] , values :: [v]} | Empty deriving Show
-- k = key, Typ variable
-- v = value, Typ variable
singleton :: (Enum k, Num k) => v -> IntervalMap k v
singleton v = IntervalMap{keys=[0..], values= repeat v}
-- get operator => a ! 5 = value at position 5
(!) :: Ord k => IntervalMap k v -> k -> v
(!) iMap k = snd (head (filter (\(x, y) -> x == k) (zip (keys iMap) (values iMap)) ))
-- insert a sequence into intervalMap
insert :: (Ord k, Num k, Enum k) => k -> k -> v -> IntervalMap k v -> IntervalMap k v
insert start end value iMap = IntervalMap {keys=keys iMap, values = rangeChanger (values iMap) start end value}
-- helper function to change a range of values in an intervalMap
rangeChanger :: (Num a1, Enum a1, Ord a1) => [a2] -> a1 -> a1 -> a2 -> [a2]
rangeChanger iMapValues start end value = [if (i >= start) && (i <= end) then newValue else iMapValue | (iMapValue, newValue, i) <- zip3 iMapValues (repeat value) [0..]]
-- functor instance for intervalMap
instance Functor (IntervalMap k) where
-- fmap :: (a -> b) -> f a -> f b
fmap f iMap = IntervalMap {keys=keys iMap, values= map f (values iMap) }
-- applicative functor for intervalMap
instance (Ord k, Num k, Enum k) => Applicative (IntervalMap k) where
pure k = IntervalMap{keys=[0..], values=repeat k}
_ <*> Nothing = Nothing
-- HOW TO DO?
-- class Functor functor => Applicative functor where
-- pure :: a -> functor a
-- (<*>) :: functor (a -> b) -> functor a -> functor b
-- (*>) :: functor a -> functor b -> functor b
-- (<*) :: functor a -> functor b -> functor a
It seems like you always expect the keys to be [0..], e.g. it is hard-coded in your rangeChanger function. If that is the case then it is redundant and honestly I would leave it out. You can easily reconstruct it by doing something like zip [0..] (values iMap) as you do in the rangeChanger function.
If you make that change, then your IntervalMap data structure is basically the same as ZipList which has an applicative instance here:
instance Applicative ZipList where
pure x = ZipList (repeat x)
liftA2 f (ZipList xs) (ZipList ys) = ZipList (zipWith f xs ys)
You see that this doesn't define a <*> but that can be defined in terms of liftA2: p <*> q = liftA2 (\f x -> f x) p q, so you could also write that explicitly for ZipList:
ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)
Edit: I should also mention that one difference with ZipList is that you have an Empty constructor for your IntervalMap type. That makes things harder, you would need to know that your values have some sort of default value, but that is not possible in general (not every type has a default value), so your type cannot be an Applicative. Do you really need that Empty case?
Consider the following Coq program:
Inductive foo : nat -> Type :=
| nil : foo 0
| succ{n:nat} : foo n -> foo n.
Fixpoint bar {n:nat}(A:foo n)(B:foo n) : Prop :=
match B with
| nil => False
| succ C => bar A C
end.
Coq complains on the definition of bar:
In environment
bar : forall n : nat, foo n -> foo n -> Prop
n : nat
A : foo n
B : foo n
n0 : nat
C : foo n0
The term "C" has type "foo n0" while it is expected to have type "foo n".
But for B : foo n to be a succ C, C must also be a foo n. Why can't Coq infer this, and how can I fix the definition of bar?
When you match on B, the type system "forgets" that the new n' inside B's type is the same as n. There is a trick to add that information to the context (there are many ways, plugins, etc. but it is good to know how to do it "by hand"). It is called "The convoy pattern" by Adam Chlipala and every coq user must post a question about that once in his/her life (your's truly included).
You make the body be not just a value but a function that takes an additional input with the type n=n' and adds an eq_refl term at the end. This plays well with how Coq's type system can break down terms.
You can either rewrite the A type to change its type from foo n to foo n' with tactics, like this:
Fixpoint bar (n:nat) (A:foo n) (B:foo n) : Prop.
refine (
match B in (foo m) return (n=m -> _) with
| nil => fun _ => False
| #succ n' B' => fun (E : n = n') => bar n' _ B'
end eq_refl).
rewrite E in A.
apply A.
Defined.
or directly with eq_rect
Fixpoint bar {n:nat} (A:foo n) (B:foo n) : Prop :=
match B in (foo m) return (n=m -> _) with
| nil => fun _ => False
| succ B' => fun E => bar (eq_rect _ _ A _ E) B'
end eq_refl.
let rec fold_inorder f acc t =
match t with
| Leaf -> acc
| Node (l, n, r) -> f (fold_inorder f acc l) (f n (fold_inorder f acc r))
I'm trying to print the infold of a tree as following :
fold_inorder (fun acc x -> acc # [x]) [] (Node (Node (Leaf,1,Leaf), 2, Node (Leaf,3,Leaf))) = [1;2;3]
I'm getting an error saying my [x] is
This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
I'm really not sure what to do from here. Can anyone nudge me in the right direction?
In your definition of fold_inorder, what type do you expect f to have?
If I look at this call:
f n (fold_inorder f acc r)
it appears that the first parameter of f is a new value from a tree node and the second parameter is an accumulated value.
But in your test call you define f like this:
(fun acc x -> ...)
This suggests that the first parameter is the accumulated value and the second parameter is a new value from a tree node.
Usually test which contain question about SML have questions that ask you to find the signature/type of a function.
For example - What is the type of the following function:
fun foo f g x y = f (f x (g x) y) y;
Solution:
val foo = fn : ('a -> 'b -> 'b -> 'a) -> ('a -> 'b) -> 'a -> 'b -> 'b -> 'a
I was wondering if there is a good algorithm I could follow in order to solve those kind of questions. Every time I try to solve one of those, I get confused and fail.
Start with what you know, then figure out a bit here and a bit there until there are no unknowns.
Here is one possibility:
Call the unknown types FOO, F, G, X, and Y, respectively.
Then look for something small and easy and start assigning types.
(g x)
is clearly an application of a function to one argument.
Set X = a and G = a -> b.
Then look at the enclosing expression:
(f x (g x) y)
| |
v v
a b
So far, we know that F = a -> b -> Y -> C, for some C.
Go outwards again:
f (f x (g x) y) y
Since both x and (f x (g x) y) are first arguments to f, they must be the same type a, and the same idea applies to y and (g x), giving them the type b.
So, F = a -> b -> b -> a and, since the outer f is only given two arguments, the type of the right-hand side must be b -> a.
Thus
X = a
Y = b
G = a -> b
F = a -> b -> b -> a
FOO = (a -> b -> b -> a) -> (a -> b) -> a -> b -> (b -> a)
And, since arrows associate to the right, FOO is equivalent to
(a -> b -> b -> a) -> (a -> b) -> a -> b -> b -> a
There are several ways to derive the type of a function depending on how close to the compiler's algorithm you want to go and how much you want to cut corners with intuition, which can come handy in practice and perhaps in exams, depending on the focus of the exam.
An example by Ionuț G. Stan cuts very few corners, and has a quite verbose notation. This mechanical approach is very safe, spells out everything and takes some time.
This current example by molbdnilo takes a middle ground and does some equational reasoning, but also relies on some level of intuition. I think this is generally the way you want to be able to do it, since it takes less time and space by hand.
An example by me links to various other examples for a diversity in practical approaches.
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.