How to define Lens into the State value itself? - haskell

While trying to understand State monad and use of Lens with it, I arrived at a surprisingly trivial definition of a lens for a simple counter:
self :: ASetter s s s s
self = ($)
incrementUsingLens :: State Int ()
incrementUsingLens = self %= (+1)
Since
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
In my case is just
type ASetter s s s s = (s -> Identity s) -> s -> Identity s
Is this is indeed a correct definition for a lens into a state variable? I'm worried that I might be missing some laws or other assumptions.

lens calls this do-nothing optic simple. Note that simple is an Equality, and Equality is at the very bottom of the optics hierarchy, which means you can use it not only as a do-nothing setter, but also as a do-nothing lens, prism, etc.
I'm worried that I might be missing some laws or other assumptions.
The setter laws say that, for a foo setter, over foo should follow the functor laws:
over foo id = id
over foo (g . f) = over foo g . over foo f
If you try this with simple/id, you will find the laws hold trivially. The same goes for the other optic laws.

Yes, ($), also called id, is also a lens in the representation of the lens package. Though here we have get, put, modify that work just as well, the identity lens can still be useful sometimes.

Related

How to avoid the warning "Redundant constraint: Functor f" in the getter?

I have some record SomeRecord and fields like _user, _password. And I want to write a Getter for a "virtual" field, like identity which will look like <user>:<password>:
identity:: Getter SomeRecord String
identity = to $ \srec -> srec^.user <> ":" <> srec^.password
and this getter leads to the warning:
• Redundant constraint: Functor f
• In the type signature for:
identity :: Getter SomeRecord Stringtypecheck(-Wredundant-constraints)
what's wrong with this getter and how to write it without warnings?
EDIT:
Just found this thread in the Web:
Comment (by ekmett):
In the interest of not getting drowned in complaints by the users of
lens on GHC 8, we'll likely just add the constraint to to and rely
on {-# INLINE #-} dropping it out in practice. This is a common
enough scenario to warrant us eating the noise on our side.
Of course, you'll get the same sort of thing if you go to declare a
non- law abiding traversal as a fold, etc. There i'm afraid the only
answer will be to squelch the warning. GHC can't see 'laws'.
This is due to the way that Edward Kmett's lens library works.
Getter is a type synonym:
type Getter s a = forall f. (Contravariant f, Functor f) => (a -> f a) -> s -> f s
Meanwhile the type of to is:
to :: (Profunctor p, Contravariant f) => (s -> a) -> Optic' p f s a
Never mind the Optic', the problem is that Getter has the constraint Functor f but the to doesn't need it. Hence the warning, because otherwise you could use it with a type f that isn't a functor.
The "proper" type for your function is something like:
identity :: (Profunctor p, Contravariant f) => Optic' p f SomeRecord String

Calling a custom monad in haskell using the bind

I am currently 'getting my feet wet with monads' (http://learnyouahaskell.com/a-fistful-of-monads#getting-our-feet-wet-with-maybe) and still struggling with part of this concept. I understand the maybe monad mentioned there and can see how to call it, as mentioned here:
ghci> return "WHAT" :: Maybe String
Just "WHAT"
ghci> Just 9 >>= \x -> return (x*10)
Just 90
ghci> Nothing >>= \x -> return (x*10)
Nothing
How do I however call my own monad instance rather than the maybe one if I declare my own instance with its own type, like so:
newtype CustomM a = CustomM {runCustomM:: a -> String}
instance Monad CustomM where
return a = CustomM (\a -> mempty)
m >>= f = CustomM (\a -> mempty)
instance Functor CustomM where
fmap = liftM
instance Applicative CustomM where
pure = return; (<*>) = ap
using the return will just call the Maybe Monad I suspect. And what about the >>= it would require me to give it a certain type.
NB. I have only made the bind the same way as the return, because I still struggle with understanding what it is supposed to return, and how I can give it a monad m and call the function f on it's value a, when I don't specify the packed type more thoroughly in the left side. But I shall make another post about that.
You can create a value of your CustomM type just like you did with Maybe, using return:
cm = return "WHAT" :: CustomM String
You can also run it, after a fashion:
Prelude Control.Monad> runCustomM cm "foo"
""
Clearly, though, since you've hard-coded it to return mempty, it returns the mempty value for String, which is "".
All that said, though, a -> String is contravariant in a, so it can't be a useful Functor instance. And since it can't be a useful Functor instance, it also can't be a useful Monad instance.
While you can define a degenerate implementation as in the OP, you're not going to have much success making CustomM do anything for real.
Try, instead, swapping the types like e.g. String -> a.

How does an environment happen to be a partially applied function, and even a hom functor?

I have seen Reader being used to major benefit many times in the wild. (One notable example would be stack, built around a straightforward derivative of Reader that can inform the user of the sufficiency of its contents on the type level.) After some thinking, I arrived to an understanding that this benefit is merely on the level of code structure, and, in a sense, all that Reader does is supply a parameter, in many places, to a complicated wiring of functions. That is, I came to believe we can always replace a reader that holds some x with a lambda abstraction of form λx. ... x ... x .... This seems to align with the official explanations that claim:
... the partially applied function type (->) r is a simple reader monad ...
However, there is a long way from noting that Reader is a way to write down a lambda abstraction piecewise, to claiming that it is a partially applied function.
Is there a function that is applied, but not partially? It would simply be a value:
λ :t id 1
id 1 :: Num a => a
λ :t 1
1 :: Num a => a
Is there a function that is not even partially applied? We'll never know:
λ :t fromMaybe
fromMaybe :: a -> Maybe a -> a
λ :t flip maybe id
flip maybe id :: b -> Maybe b -> b
Even ignoring this as nitpicking, I would not take on faith that (->) r (why not just write (r ->)?) is exactly and singularly a Reader monad. Maybe I could write an instance that typechecks. Maybe it would even obey the laws. As long as I do not think of my functions as Readers, as long as I do not have the right intuition, the vision of it, it is as useful to me as the first proof of the Four Colour Theorem. On the other hand, how can I be sure this is the only way of defining a monad on functions? There are several Monoids on Num, at least two Applicatives on Lists − would it not be too reckless to consider a function a Reader monad alone?
The predicament does not end here. Once I go searching for an answer, I stumble upon an even more puzzling note: Reader happens to be the hom functor now, or even a representable functor in general. And the folks from the other end of the spectrum actually know ahead of time that there would be such a construct in Haskell, and even spell its type, the same as it is spelled in the aforementioned official explanations. Now, this is way over my head, but I can parse the definition of hom functor from Mac Lane. With some imagination, it can be seen that, granted a function a -> b as a morphism in the (supposed) category Hask, we may compose it with id to obtain... a function a -> b again, this time as an element of the set hom(a, b).
Does this connect in any way with some of these morphisms being partially applied? Or with the use of Reader as option store in stack? Can I actually be shown the object and arrow functions of the hom functor Hask -> Set? (I shall take an endofunctor Hask -> Hask as a reasonable approximation.) Would that be my trusty fellows pure and fmap?
And, well, how do I actually use Reader, after that?
I can't answer all of your questions, but let's start with the easy ones:
(->) r (why not just write (r ->)?)
Because the latter is a syntax error in Haskell. You can't use this section syntax on types.
... claiming that it is a partially applied function.
That's not what it's saying. The quote is:
the partially applied function type (->) r is a simple reader monad
It's a partially applied type, not a partially applied function. Or in other words, it's parsed like this: ((partially applied) (function type))
The type constructor for function types in Haskell is spelled ->.
A fully applied function type looks like r -> a (or equivalently (->) r a), where r is the argument type and a the result type.
Thus (->) r is a partial application of -> (the function type).
If we ignore monad transformers and ReaderT, the straightforward definition of Reader is:
newtype Reader r a = Reader (r -> a)
runReader :: Reader r a -> r -> a
runReader (Reader f) x = f x
-- or rather:
runReader :: Reader r a -> (r -> a)
runReader (Reader f) = f
or equivalently:
newtype Reader r a = Reader{ runReader :: r -> a }
That is, Reader is just a newtype for -> (a very thin wrapper), with runReader for unwrapping.
You can even make -> an instance of MonadReader just by copying the instance for Reader and removing all the Reader / runReader wrapping/unwrapping.

What's the difference between parametric polymorphism and higher-kinded types?

I am pretty sure they are not the same. However, I am bogged down by the
common notion that "Rust does not support" higher-kinded types (HKT), but
instead offers parametric polymorphism. I tried to get my head around that and understand the difference between these, but got just more and more entangled.
To my understanding, there are higher-kinded types in Rust, at least the basics. Using the "*"-notation, a HKT does have a kind of e.g. * -> *.
For example, Maybe is of kind * -> * and could be implemented like this in Haskell.
data Maybe a = Just a | Nothing
Here,
Maybe is a type constructor and needs to be applied to a concrete type
to become a concrete type of kind "*".
Just a and Nothing are data constructors.
In textbooks about Haskell, this is often used as an example for a higher-kinded type. However, in Rust it can simply be implemented as an enum, which after all is a sum type:
enum Maybe<T> {
Just(T),
Nothing,
}
Where is the difference? To my understanding this is a
perfectly fine example of a higher-kinded type.
If in Haskell this is used as a textbook example of HKTs, why is it
said that Rust doesn't have HKT? Doesn't the Maybe enum qualify as a
HKT?
Should it rather be said that Rust doesn't fully support HKT?
What's the fundamental difference between HKT and parametric polymorphism?
This confusion continues when looking at functions, I can write a parametric
function that takes a Maybe, and to my understanding a HKT as a function
argument.
fn do_something<T>(input: Maybe<T>) {
// implementation
}
again, in Haskell that would be something like
do_something :: Maybe a -> ()
do_something :: Maybe a -> ()
do_something _ = ()
which leads to the fourth question.
Where exactly does the support for higher-kinded types end? Whats the
minimal example to make Rust's type system fail to express HKT?
Related Questions:
I went through a lot of questions related to the topic (including links they have to blogposts, etc.) but I could not find an answer to my main questions (1 and 2).
In Haskell, are "higher-kinded types" *really* types? Or do they merely denote collections of *concrete* types and nothing more?
Generic struct over a generic type without type parameter
Higher Kinded Types in Scala
What types of problems helps "higher-kinded polymorphism" solve better?
Abstract Data Types vs. Parametric Polymorphism in Haskell
Update
Thank you for the many good answers which are all very detailed and helped a lot. I decided to accept Andreas Rossberg's answer since his explanation helped me the most to get on the right track. Especially the part about terminology.
I was really locked in the cycle of thinking that everything of kind * -> * ... -> * is higher-kinded. The explanation that stressed the difference between * -> * -> * and (* -> *) -> * was crucial for me.
Some terminology:
The kind * is sometimes called ground. You can think of it as 0th order.
Any kind of the form * -> * -> ... -> * with at least one arrow is first-order.
A higher-order kind is one that has a "nested arrow on the left", e.g., (* -> *) -> *.
The order essentially is the depth of left-side nesting of arrows, e.g., (* -> *) -> * is second-order, ((* -> *) -> *) -> * is third-order, etc. (FWIW, the same notion applies to types themselves: a second-order function is one whose type has e.g. the form (A -> B) -> C.)
Types of non-ground kind (order > 0) are also called type constructors (and some literature only refers to types of ground kind as "types"). A higher-kinded type (constructor) is one whose kind is higher-order (order > 1).
Consequently, a higher-kinded type is one that takes an argument of non-ground kind. That would require type variables of non-ground kind, which are not supported in many languages. Examples in Haskell:
type Ground = Int
type FirstOrder a = Maybe a -- a is ground
type SecondOrder c = c Int -- c is a first-order constructor
type ThirdOrder c = c Maybe -- c is second-order
The latter two are higher-kinded.
Likewise, higher-kinded polymorphism describes the presence of (parametrically) polymorphic values that abstract over types that are not ground. Again, few languages support that. Example:
f : forall c. c Int -> c Int -- c is a constructor
The statement that Rust supports parametric polymorphism "instead" of higher-kinded types does not make sense. Both are different dimensions of parameterisation that complement each other. And when you combine both you have higher-kinded polymorphism.
A simple example of what Rust can't do is something like Haskell's Functor class.
class Functor f where
fmap :: (a -> b) -> f a -> f b
-- a couple examples:
instance Functor Maybe where
-- fmap :: (a -> b) -> Maybe a -> Maybe b
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)
instance Functor [] where
-- fmap :: (a -> b) -> [a] -> [b]
fmap _ [] = []
fmap f (x:xs) = f x : fmap f xs
Note that the instances are defined on the type constructor, Maybe or [], instead of the fully-applied type Maybe a or [a].
This isn't just a parlor trick. It has a strong interaction with parametric polymorphism. Since the type variables a and b in the type fmap are not constrained by the class definition, instances of Functor cannot change their behavior based on them. This is an incredibly strong property in reasoning about code from types, and where a lot of where the strength of Haskell's type system comes from.
It has one other property - you can write code that's abstract in higher-kinded type variables. Here's a couple examples:
focusFirst :: Functor f => (a -> f b) -> (a, c) -> f (b, c)
focusFirst f (a, c) = fmap (\x -> (x, c)) (f a)
focusSecond :: Functor f => (a -> f b) -> (c, a) -> f (c, b)
focusSecond f (c, a) = fmap (\x -> (c, x)) (f a)
I admit, those types are beginning to look like abstract nonsense. But they turn out to be really practical when you have a couple helpers that take advantage of the higher-kinded abstraction.
newtype Identity a = Identity { runIdentity :: a }
instance Functor Identity where
-- fmap :: (a -> b) -> Identity a -> Identity b
fmap f (Identity x) = Identity (f x)
newtype Const c b = Const { getConst :: c }
instance Functor (Const c) where
-- fmap :: (a -> b) -> Const c a -> Const c b
fmap _ (Const c) = Const c
set :: ((a -> Identity b) -> s -> Identity t) -> b -> s -> t
set f b s = runIdentity (f (\_ -> Identity b) s)
get :: ((a -> Const a b) -> s -> Const a t) -> s -> a
get f s = getConst (f (\x -> Const x) s)
(If I made any mistakes in there, can someone just fix them? I'm reimplementing the most basic starting point of lens from memory without a compiler.)
The functions focusFirst and focusSecond can be passed as the first argument to either get or set, because the type variable f in their types can be unified with the more concrete types in get and set. Being able to abstract over the higher-kinded type variable f allows functions of a particular shape can be used both as setters and getters in arbitrary data types. This is one of the two core insights that led to the lens library. It couldn't exist without this kind of abstraction.
(For what it's worth, the other key insight is that defining lenses as a function like that allows composition of lenses to be simple function composition.)
So no, there's more to it than just being able to accept a type variable. The important part is being able to use type variables that correspond to type constructors, rather than some concrete (if unknown) type.
I'm going to resume it: a higher-kinded type is just a type-level higher-order function.
But take a minute:
Consider monad transformers:
newtype StateT s m a :: * -> (* -> *) -> * -> *
Here,
- s is the desired type of the state
- m is a functor, another monad that StateT will wrap
- a is the return type of an expression of type StateT s m
What is the higher-kinded type?
m :: (* -> *)
Because takes a type of kind * and returns a kind of type *.
It's like a function on types, that is, a type constructor of kind
* -> *
In languages like Java, you can't do
class ClassExample<T, a> {
T<a> function()
}
In Haskell T would have kind *->*, but a Java type (i.e. class) cannot have a type parameter of that kind, a higher-kinded type.
Also, if you don't know, in basic Haskell an expression must have a type that has kind *, that is, a "concrete type". Any other type like * -> *.
For instance, you can't create an expression of type Maybe. It has to be types applied to an argument like Maybe Int, Maybe String, etc. In other words, fully applied type constructors.
Parametric polymorphism just refers to the property that the function cannot make use of any particular feature of a type (or kind) in its definition; it is a complete blackbox. The standard example is length :: [a] -> Int, which only works with the structure of the list, not the particular values stored in the list.
The standard example of HKT is the Functor class, where fmap :: (a -> b) -> f a -> f b. Unlike length, where a has kind *, f has kind * -> *. fmap also exhibits parametric polymorphism, because fmap cannot make use of any property of either a or b in its definition.
fmap exhibits ad hoc polymorphism as well, because the definition can be tailored to the specific type constructor f for which it is defined. That is, there are separate definitions of fmap for f ~ [], f ~ Maybe, etc. The difference is that f is "declared" as part of the typeclass definition, rather than just being part of the definition of fmap. (Indeed, typeclasses were added to support some degree of ad hoc polymorphism. Without type classes, only parametric polymorphism exists. You can write a function that supports one concrete type or any concrete type, but not some smaller collection in between.)

Any advantage of using type constructors in type classes?

Take for example the class Functor:
class Functor a
instance Functor Maybe
Here Maybe is a type constructor.
But we can do this in two other ways:
Firstly, using multi-parameter type classes:
class MultiFunctor a e
instance MultiFunctor (Maybe a) a
Secondly using type families:
class MonoFunctor a
instance MonoFunctor (Maybe a)
type family Element
type instance Element (Maybe a) a
Now there's one obvious advantage of the two latter methods, namely that it allows us to do things like this:
instance Text Char
Or:
instance Text
type instance Element Text Char
So we can work with monomorphic containers.
The second advantage is that we can make instances of types that don't have the type parameter as the final parameter. Lets say we make an Either style type but put the types the wrong way around:
data Silly t errorT = Silly t errorT
instance Functor Silly -- oh no we can't do this without a newtype wrapper
Whereas
instance MultiFunctor (Silly t errorT) t
works fine and
instance MonoFunctor (Silly t errorT)
type instance Element (Silly t errorT) t
is also good.
Given these flexibility advantages of only using complete types (not type signatures) in type class definitions, is there any reason to use the original style definition, assuming you're using GHC and don't mind using the extensions? That is, is there anything special you can do putting a type constructor, not just a full type in a type class that you can't do with multi-parameter type classes or type families?
Your proposals ignore some rather important details about the existing Functor definition because you didn't work through the details of writing out what would happen with the class's member function.
class MultiFunctor a e where
mfmap :: (e -> ??) -> a -> ????
instance MultiFunctor (Maybe a) a where
mfmap = ???????
An important property of fmap at the moment is that its first argument can change types. fmap show :: (Functor f, Show a) => f a -> f String. You can't just throw that away, or you lose most of the value of fmap. So really, MultiFunctor would need to look more like...
class MultiFunctor s t a b | s -> a, t -> b, s b -> t, t a -> s where
mfmap :: (a -> b) -> s -> t
instance (a ~ c, b ~ d) => MultiFunctor (Maybe a) (Maybe b) c d where
mfmap _ Nothing = Nothing
mfmap f (Just a) = Just (f a)
Note just how incredibly complicated this has become to try to make inference at least close to possible. All the functional dependencies are in place to allow instance selection without annotating types all over the place. (I may have missed a couple possible functional dependencies in there!) The instance itself grew some crazy type equality constraints to allow instance selection to be more reliable. And the worst part is - this still has worse properties for reasoning than fmap does.
Supposing my previous instance didn't exist, I could write an instance like this:
instance MultiFunctor (Maybe Int) (Maybe Int) Int Int where
mfmap _ Nothing = Nothing
mfmap f (Just a) = Just (if f a == a then a else f a * 2)
This is broken, of course - but it's broken in a new way that wasn't even possible before. A really important part of the definition of Functor is that the types a and b in fmap don't appear anywhere in the instance definition. Just looking at the class is enough to tell the programmer that the behavior of fmap cannot depend on the types a and b. You get that guarantee for free. You don't need to trust that instances were written correctly.
Because fmap gives you that guarantee for free, you don't even need to check both Functor laws when defining an instance. It's sufficient to check the law fmap id x == x. The second law comes along for free when the first law is proven. But with that broken mfmap I just provided, mfmap id x == x is true, even though the second law is not.
As the implementer of mfmap, you have more work to do to prove your implementation is correct. As a user of it, you have to put more trust in the implementation's correctness, since the type system can't guarantee as much.
If you work out more complete examples for the other systems, you find that they have just as many issues if you want to support the full functionality of fmap. And this is why they aren't really used. They add a lot of complexity for only a small gain in utility.
Well, for one thing the traditional functor class is just much simpler. That alone is a valid reason to prefer it, even though this is Haskell and not Python. And it also represents the mathematical idea better of what a functor is supposed to be: a mapping from objects to objects (f :: *->*), with extra property (->Constraint) that each (forall (a::*) (b::*)) morphism (a->b) is lifted to a morphism on the corresponding object mapped to (-> f a->f b). None of that can be seen very clearly in the * -> * -> Constraint version of the class, or its TypeFamilies equivalent.
On a more practical account, yes, there are also things you can only do with the (*->*)->Constraint version.
In particular, what this constraint guarantees you right away is that all Haskell types are valid objects you can put into the functor, whereas for MultiFunctor you need to check every possible contained type, one by one. Sometimes that's just not possible (or is it?), like when you're mapping over infinitely many types:
data Tough f a = Doable (f a)
| Tough (f (Tough f (a, a)))
instance (Applicative f) = Semigroup (Tough f a) where
Doable x <> Doable y = Tough . Doable $ (,)<$>x<*>y
Tough xs <> Tough ys = Tough $ xs <> ys
-- The following actually violates the semigroup associativity law. Hardly matters here I suppose...
xs <> Doable y = xs <> Tough (Doable $ fmap twice y)
Doable x <> ys = Tough (Doable $ fmap twice x) <> ys
twice x = (x,x)
Note that this uses the Applicative instance of f not just on the a type, but also on arbitrary tuples thereof. I can't see how you could express that with a MultiParamTypeClasses- or TypeFamilies-based applicative class. (It might be possible if you make Tough a suitable GADT, but without that... probably not.)
BTW, this example is perhaps not as useless as it may look – it basically expresses read-only vectors of length 2n in a monadic state.
The expanded variant is indeed more flexible. It was used e.g. by Oleg Kiselyov to define restricted monads. Roughly, you can have
class MN2 m a where
ret2 :: a -> m a
class (MN2 m a, MN2 m b) => MN3 m a b where
bind2 :: m a -> (a -> m b) -> m b
allowing monad instances to be parametrized over a and b. This is useful because you can restrict those types to members of some other class:
import Data.Set as Set
instance MN2 Set.Set a where
-- does not require Ord
return = Set.singleton
instance Prelude.Ord b => MN3 SMPlus a b where
-- Set.union requires Ord
m >>= f = Set.fold (Set.union . f) Set.empty m
Note than because of that Ord constraint, we are unable to define Monad Set.Set using unrestricted monads. Indeed, the monad class requires the monad to be usable at all types.
Also see: parameterized (indexed) monad.

Resources