Haskell: functor from this data type? - haskell

Sorry about bad title. I have a problematic data type, which I'm trying to define as instance of functor.
So basically, what I have is something, which has
sample_logp :: s a -> a
and it should be transformed using
(a -> b)
to
sample_logp :: s b -> b
. The following code does not quite accomplish this, and succeeds only in
sample_logp :: s a -> b
.
data Model s a = Model {
sample_logp :: s a -> a
}
instance Functor (Model s) where
fmap f m = Model {
sample_logp = sample_logp'
} where sample_logp' x = (f . (sample_logp m)) x
Is what I'm trying even possible? If so, how could this code be updated to achieve this?

The standard approach here is to add more type variables.
data Model s a b = Model {
sample_logp :: s a -> b
}
Once you have split the type variables, you have access to more tools. The Profunctor class is appropriate here. (Not typechecked since I don't have ghc on this system - comment or just fix it if my implementation is off.)
instance (Functor s) => Profunctor (Model s) where
dimap f g (Model h) = Model $ g . h . fmap f
lmap f (Model h) = Model $ h . fmap f
rmap g (Model h) = Model $ g . h
Now, given that you have a Model s a a, which is the equivalent of your Model s a, you can convert it to a Model s b b by using dimap bToA aToB.
As the comments say, your original data type is invariant because it uses the same type variable in positive and negative positions. This means you need to supply conversion functions in each direction. Adding an extra type variable lets you take advantage of existing tools for doing that, like Profunctor.
Note that all of the above is based on the assumption that you are using covariant types for s. If s is contravariant, then you can write a direct Functor instance for your original type, as chi's comment says. That's a much less common situation, though.

Related

Free theorem for fmap

Consider the following wrapper:
newtype F a = Wrap { unwrap :: Int }
I want to disprove (as an exercise to wrap my head around this interesting post) that there’s a legitimate Functor F instance which allows us to apply functions of Int -> Int type to the actual contents and to ~ignore~ all other functions (i. e. fmap nonIntInt = id).
I believe this should be done with a free theorem for fmap (which I read here):
for given f, g, h and k, such that g . f = k . h: $map g . fmap f = fmap k . $map h, where $map is the natural map for the given constructor.
What defines a natural map? Am I right to assume that it is a simple flip const for F?
As far as I get it: $map f is what we denote as Ff in category theory. Thus, in a categorical sense, we simply want something among the lines of the following diagram to commute:
Yet, I do not know what to put instead of ???s (that is, what functor do we apply to get such a diagram and how do we denote this almost-fmap?).
So, what is a natural map in general, and for F? What is the proper diagram for fmap's free theorem?
Where am I going with this?
Consider:
f = const 42
g = id
h = const ()
k () = 42
It is easy to see that f . g is h . k. And yet, the non-existant fmap will execute only f, not k, giving different results. If my intuition about the naturality is correct, such a proof would work. That's what I am trying to figure out.
#leftaroundabout proposed a simpler piece of proof: fmap show . fmap (+1) alters the contents, unlike fmap $ show . (+1). It is a nice piece of proof, and yet I would still like to work with free theorems as an exercise.
So we are entertaining a function m :: forall a b . (a->b) -> F a -> F b such that (among other things)
m (1 +) (Wrap x) = (Wrap (1+x))
m (show) (Wrap x) = (Wrap x)
There are two somewhat related questions here.
Can a well-behaved fmap do this?
Can a parametric function do this?
The answer to both questions is "no".
A well-behaved fmap can't do this because fmap has to obey the axioms of Functor. Whether our environment is parametric or not is irrelevant. The axiom of Functor says that for all functions a and b, fmap (a . b) = fmap a . fmap b must hold, and this fails for a = show and b = (1 +). So m cannot be a well-behaved fmap.
A parametric function can't do this because that is what the parametricity theorem says. When viewing types as relations between terms, related functions take related arguments to related results. It is easy to see that m fails parametricity, but it is slightly easier to look at m': forall a b. (a -> b) -> (Int -> Int) (the two can be trivially converted to each other). (1 +) is related to show because m' is polymorphic in its argument, so different values of the argument can be related by any relation. Functions are relations, and there exists a function that sends (1 +) to show. However, the result type of m' has no type variables, so it corresponds to the constant relation (its values are only related to themselves). Since every value including m' is related to itself, it follows that all parametric functions m :: forall a b. (a -> b) -> (Int -> Int) must obey m f = m g, i.e. they must ignore their first argument. Which is intuitively obvious since there is nothing to apply it to.
One can in fact deduce the first statement from the second by observing that a well-behaved fmap must be parametric. So even if the language allows non-parametricity, fmap cannot make any non-trivial use of it.

Optimize Superclass Method Depending on Subclass

Can I provide a refined implementation (aka. override in OOP) of a method in a class instance, when the type is in another class, too? Or at least, if that other class is a subclass.
I have a class C with method m, a subclass S of C with method s and a type T a so there are instantiations
class C a where m :: [a] -> Bool
class C a => S a where s :: a -> a -> Bool
instance C a => C (T a) where m = ...
instance S a => S (T a) where s = ...
as usual.
Now it happens to be that when T a is in the subclass (which I cannot know as it depends on a), method m could be implemented much more efficient (quadratic vs. exponential time) using s.
I tried 'overriding' m in the implementation
instance S a => S (T a) where
s = ...
m = (all . uncurry) (=^=) . pairs -- override C.m
but the compiler errors basically because, m is not a public method of S. Well, it is not, but it's inherited in the OO sense.
For the specific purpose, the specialized version of m can be used for all instances; it's not a default to be overridden anywhere.
Edit: Because requested, the concrete code with a bit of explanation.
I have a class Model which has (among others) a method con that checks a list for consistency.
class Model a where
con :: [a] -> Bool
Two models can form an arrow model.
data Arrow a b = [a] :->: b
lhs w = [ a | (u :->: _) <- w, a <- u ]
rhs w = [ b | (_ :->: b) <- w ]
For the specific instance Model (Arrow a b), the general con implementation is very expensive (note powerset in the definition).
instance (Model a, Model b) => Model (Arrow a b) where
con w = all (\w' -> con (lhs w') `implies` con (rhs w')) (powerset w)
There is a subclass CoherentModel of Model which has a method (=^=) that checks consistency for two objects. The condition for coherent models is that a list is consistent iff all pairs are.
class Model a => CoherentModel a where
(=^=) :: a -> a -> Bool
a =^= b = con [a, b]
The class CoherentModel is at this point more documentation than a feature.
So, given that a model is coherent, consistency is much more efficient to check.
instance (Model a, CoherentModel b) => CoherentModel (Arrow a b) where
(u :->: a) =^= (v :->: b) = con (u ++ v) `implies` a =^= b
And in this case, con can be implemented using
con = (all . uncurry) (=^=) . pairs
where
pairs :: [a] -> [(a,a)]
pairs [] = []
pairs [_] = []
pairs [x,y] = [(x,y)]
pairs (x:xs) = map ((,) x) xs ++ pairs xs
but I find no way to specify this. It's not only for Arrow, it's relevant for all models with parameter. I chose Arrow because the improvement is significant.
It's a good question. One thing to remember is that whether a data type is an instance of a typeclass is compile-time only information -- i.e. we are always able to choose which instance to use using statically available information at the use site, and polymorphism comes from being able to choose an instance from the context. In general, if you ask "is a a member of typeclass B?", the only answers you can get are "yes" and "compile error". (This second observation is changed a bit by OverlappingInstances, but it doesn't seem to help in your case)
So the answer to your immediate question is no. You can't make a decision about a type's membership in a type class unless you are a method of that type class. What we can do is add this decision as a method (using the constraints package)
import Data.Constraint
class Model a where
con :: [a] -> Bool
isCoherent :: Maybe (Dict (CoherentModel a))
isCoherent = Nothing
Which you can define trivially for any type you have instantiated CoherentModel at:
instance Model Foo where
con = ...
isCoherent = Just Dict
Now you can implement your decision like this (w/ extensions ScopedTypeVariables and TypeApplications):
instance (Model a, Model b) => Model (Arrow a b) where
con | Just Dict <- isCoherent #b = -- efficient implementation
| otherwise = -- inefficient implementation
In the body of the first case we will have a local CoherentModel b in the context. It's kind of cool.
Too bad we have a sort of expression problem here where all the different implementations of con need to be collected up into one place. Also too bad isCoherent needs to be implemented manually on each coherent Model instance, separate from where its CoherentModel instance is.
There is a lot to explore here but I have to go. Good luck!

Monads, "container" exercise from sigfpe's blog

I'm working my way through "Learn You a Haskell" and am now at the chapter on monads. In other Haskell-related posts, I saw a number of folks recommend sigfpe's blog post on monads; it was highly recommended that a Haskell student go through his various exercises which allow the reader to "invent" / "discover" the concept of monads for himself/herself.
I'm having trouble with the last step of the set of exercises on containers. I think it would be against forum rules to link to his site, so I'll do my best to describe it here. (Lmk if I'm wrong on this front.) As a heads up, my description of the exercise may not be entirely coherent so a simple google search may be best :)
Overview:
Each set of exercises walks the reader through the step of constructing a different type of monad. A general outline of the steps is as follows:
We consider two functions - f' and g' - which have the same type declaration
We construct a function (bind) which allows us to compose f and g such that the output is meaningful (probably makes more sense once you see the specific exercise below). Straight composition doesn't work since the return type of f and g doesn't match their argument type.
Next, we define an identity function (unit) such that the following is true:
(bind unit . f') == (bind f' . unit)
Based on the previous step, we define a lift function such that lift f = unit . f
In the last step, we are asked to show that the following holds true:
bind (lift f) (lift g) == lift . bind f g
Here's the set of exercises I'm working on:
We are asked to consider two functions sqrt' and cbrt' which calculate the square and cube roots of complex numbers (i.e., numbers of the form a + bi where a and b are real numbers and i is the square root of negative one). The underlying math isn't important. What's important is that the number of n-th roots possible is n. In other words, a complex number (i.e., of the form a + bi) has are two square roots of a complex number, three cube roots of a complex number, etc.
Given the nature of complex roots, it makes sense that both sqrt' and cbrt' take an argument of type Complex and return type [Complex]. We are asked to construct a bind function which lets us calculate the sixth root of a complex number while leveraging the fact that we already have sqrt' and cbrt'. (Straight composition obv won't work)
bind :: (Complex -> [Complex) -> [Complex] -> [Complex]
bind f = (concat . map f)
Next, we construct unit and lift:
unit :: Complex -> [Complex]
unit x = [x]
lift :: (Complex -> [Complex]) -> Complex -> [Complex]
lift f = unit . f
In the last step (and this is what I'm having trouble with), we're asked to show the following:
bind (lift f) (lift g) == lift . bind f g
First of all, doesn't the left-hand side of this equation have a type-mismatch in that lift can't accept an argument of type [Complex]? Taking a step back, I'm not sure as to why we even bother defining unit and lift. (My naive self thinks that the definition of bind solves the problem at hand therefore on to the next question.) I'd greatly appreciate if someone could help me understand why we define these two functions and then seek to prove the very last equality.
As reference, am attaching my code below. Please note that the bind, unit and lift functions have generalized type declarations.
bind :: (a1 -> [a]) -> [a1] -> [a]
bind f' = (concat . map f')
unit :: t -> [t]
unit x = [x]
lift :: (a -> b) -> a -> [b]
lift f = unit . f
--Definitions of cbRootC and sqRootC
data Complex = Complex Float Float deriving (Show)
cbrt' = rootC 3
sqrt' = rootC 2
rootC :: Float -> Complex -> [Complex]
rootC n (Complex a b) = zipWith Complex r i
where r = map (* (mod ** (1/n) )) $ map cos $ map arg [0..n-1]
i = map (* (mod ** (1/n) )) $ map sin $ map arg [0..n-1]
arg = ( * (2*pi / n) )
mod = sqrt (a*a + b*b)
Your first misunderstanding is in the type of lift. In the description of the problem you list it as the first of the following, but in your code you have the second.
lift :: (Complex -> [Complex]) -> Complex -> [Complex]
lift :: (a -> b ) -> a -> [b]
Notice how the second definition doesn't include [] around the return type of the first argument. The second one is correct. lift is going to take an ordinary function Complex -> Complex and produce a "multivalued" computation from it Complex -> [Complex], which for the multiple values only returns the single value returned from the ordinary function.
Your second misunderstanding has to do with how * and . are used in sigfpe's article. * is used to compose "multivalued" computations together; f * g = bind f . g. . is used for ordinary function composition.
You aren't asked to show that
bind (lift f) (lift g) == lift . bind f g
You are correct that this doesn't typecheck. Let's try for exercise. bind applied to two arguments returns [a]. lift applied to a single argument returns an a1 -> [b]
bind (lift f) (lift g) == lift . bind f g
[a] ~ a1 -> [b]
There's no choice of a, a1, and b that will make a list [] and function -> have the same type.
Instead you are asked to show the following. Notice the different symbols * and .. We'll replace * with bind and ..
lift f * lift g == lift (f . g)
bind (lift f) . (lift g) == lift (f . g)
I'll leave the remainder of the exercise for you.
The reason unit and lift are useful is they allow you to reuse things of ordinary types that you already have. lift turns ordinary functions into "multivalued" computations and unit turns ordinary values into the results of "multivalued" computations.

How can a function be "transparently augmented" in Haskell?

Situation
I have function f, which I want to augment with function g, resulting in function named h.
Definitions
By "augment", in the general case, I mean: transform either input (one or more arguments) or output (return value) of function f.
By "augment", in the specific case, (specific to my current situation) I mean: transform only the output (return value) of function f while leaving all the arguments intact.
By "transparent", in the context of "augmentation", (both the general case and the specific case) I mean: To couple g's implementation as loosely to f's implementation as possible.
Specific case
In my current situation, this is what I need to do:
h a b c = g $ f a b c
I am interested in rewriting it to something like this:
h = g . f -- Doesn't type-check.
Because from the perspective of h and g, it doesn't matter what arguments f take, they only care about the return value, hence it would be tight coupling to mention the arguments in any way. For instance, if f's argument count changes in the future, h will also need to be changed.
So far
I asked lambdabot on the #haskell IRC channel: #pl h a b c = g $ f a b c to which I got the response:
h = ((g .) .) . f
Which is still not good enough since the number of (.)'s is dependent on the number of f's arguments.
General case
I haven't done much research in this direction, but erisco on #haskell pointed me towards http://matt.immute.net/content/pointless-fun which hints to me that a solution for the general case could be possible.
So far
Using the functions defined by Luke Palmer in the above article this seems to be an equivalent of what we have discussed so far:
h = f $. id ~> id ~> id ~> g
However, it seems that this method sadly also suffers from being dependent on the number of arguments of f if we want to transform the return value of f -- just as the previous methods.
Working example
In JavaScript, for instance, it is possible to achieve transparent augmentation like this:
function h () { return g(f.apply(this, arguments)) }
Question
How can a function be "transparently augmented" in Haskell?
I am mainly interested in the specific case, but it would be also nice to know how to handle the general case.
You can sort-of do it, but since there is no way to specify a behavior for everything that isn't a function, you'll need a lot of trivial instances for all the other types you care about.
{-# LANGUAGE TypeFamilies, DefaultSignatures #-}
class Augment a where
type Result a
type Result a = a
type Augmented a r
type Augmented a r = r
augment :: (Result a -> r) -> a -> Augmented a r
default augment :: (a -> r) -> a -> r
augment g x = g x
instance Augment b => Augment (a -> b) where
type Result (a -> b) = Result b
type Augmented (a -> b) r = a -> Augmented b r
augment g f x = augment g (f x)
instance Augment Bool
instance Augment Char
instance Augment Integer
instance Augment [a]
-- and so on for every result type of every function you want to augment...
Example:
> let g n x ys = replicate n x ++ ys
> g 2 'a' "bc"
"aabc"
> let g' = augment length g
> g' 2 'a' "bc"
4
> :t g
g :: Int -> a -> [a] -> [a]
> :t g'
g' :: Int -> a -> [a] -> Int
Well, technically, with just enough IncoherentInstances you can do pretty much anything:
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies,
FlexibleInstances, UndecidableInstances, IncoherentInstances #-}
class Augment a b f h where
augment :: (a -> b) -> f -> h
instance (a ~ c, h ~ b) => Augment a b c h where
augment = ($)
instance (Augment a b d h', h ~ (c -> h')) => Augment a b (c -> d) h where
augment g f = augment g . f
-- Usage
t1 = augment not not
r1 = t1 True
t2 = augment (+1) (+)
r2 = t2 2 3
t3 = augment (+1) foldr
r3 = t3 (+) 0 [2,3]
The problem is that the real return value of something like a -> b -> c isn't
c, but b -> c. What you want require some kind of test that tells you if a type isn't
a function type. You could enumerate the types you are interested in, but that's not so
nice. I think HList solve this problem somehow, look at the paper. I managed to understand a bit of the solution with overlapping instances, but the rest goes a bit over my head I'm afraid.
JavaScript works, because its arguments are a sequence, or a list, so there is just one argument, really. In that sense it is the same as a curried version of the functions with a tuple representing the collection of arguments.
In a strongly typed language you need a lot more information to do that "transparently" for a function type - for example, dependent types can express this idea, but require the functions to be of specific types, not a arbitrary function type.
I think I saw a workaround in Haskell that can do this, too, but, again, that works only for specific types, which capture the arity of the function, not any function.

How much is applicative really about applying, rather than "combining"?

For an uncertainty-propagating Approximate type, I'd like to have instances for Functor through Monad. This however doesn't work because I need a vector space structure on the contained types, so it must actually be restricted versions of the classes. As there still doesn't seem to be a standard library for those (or is there? please point me. There's rmonad, but it uses * rather than Constraint as the context kind, which seems just outdated to me), I wrote my own version for the time being.
It all works easy for Functor
class CFunctor f where
type CFunctorCtxt f a :: Constraint
cfmap :: (CFunctorCtxt f a, CFunctorCtxt f b) => (a -> b) -> f a -> f b
instance CFunctor Approximate where
type CFunctorCtxt Approximate a = FScalarBasisSpace a
f `cfmap` Approximate v us = Approximate v' us'
where v' = f v
us' = ...
but a direct translation of Applicative, like
class CFunctor f => CApplicative' f where
type CApplicative'Ctxt f a :: Constraint
cpure' :: (CApplicative'Ctxt f a) => a -> f a
(#<*>#) :: ( CApplicative'Ctxt f a
, CApplicative'Ctxt f (a->b)
, CApplicative'Ctxt f b) => f(a->b) -> f a -> f b
is not possible because functions a->b do not have the necessary vector space structure* FScalarBasisSpace.
What does work, however, is to change the definition of the restricted applicative class:
class CFunctor f => CApplicative f where
type CApplicativeCtxt f a :: Constraint
cpure :: CAppFunctorCtxt f a => a -> f a
cliftA2 :: ( CAppFunctorCtxt f a
, CAppFunctorCtxt f b
, CAppFunctorCtxt f c ) => (a->b->c) -> f a -> f b -> f c
and then defining <*># rather than cliftA2 as a free function
(<*>#) = cliftA2 ($)
instead of a method. Without the constraint, that's completely equivalent (in fact, many Applicative instances go this way anyway), but in this case it's actually better: (<*>#) still has the constraint on a->b which Approximate can't fulfill, but that doesn't hurt the applicative instance, and I can still do useful stuff like
ghci> cliftA2 (\x y -> (x+y)/x^2) (3±0.2) (5±0.3) :: Approximate Double
0.8888888888888888 +/- 0.10301238090045711
I reckon the situation would essentially the same for many other uses of CApplicative, for instance the Set example that's already given in the original blog post on constraint kinds.
So my question:
is <*> more fundamental than liftA2?
Again, in the unconstrained case they're equivalent anyway. I actually have found liftA2 easier to understand, but in Haskell it's probably just more natural to think about passing "containers of functions" rather than containers of objects and some "global" operation to combine them. And <*> directly induces all the liftAμ for μ ∊ ℕ, not just liftA2; doing that from liftA2 only doesn't really work.
But then, these constrained classes seem to make quite a point for liftA2. In particular, it allows CApplicative instances for all CMonads, which does not work when <*># is the base method. And I think we all agree that Applicative should always be more general than Monad.
What would the category theorists say to all of this? And is there a way to get the general liftAμ without a->b needing to fulfill the associated constraint?
*Linear functions of that type actually do have the vector space structure, but I definitely can't restrict myself to those.
As I understand it (as a non---category theorist), the fundamental operation is zip :: f a -> f b -> f (a, b) (mapping a pair of effectful computations to an effectful computation resulting in a pair).
You can then define
fx <*> fy = uncurry ($) <$> zip fx fy
liftA2 g fx fy = uncurry g <$> zip fx fy
See this post by Edward Yang, which I found via the Typeclassopedia.

Resources