Lifting const 
Tags: functional, haskell
Published: 2019-09-23 23:05:21

---
title: Lifting const 
published: true
description: #100DaysOfFP Day 24: behavior of const lifted into applicative context
series: 100 Days Of FP
tags: fp,haskell
cover_image: https://thepracticaldev.s3.amazonaws.com/i/y9xvvsj06l36cacnoq3p.jpeg
---

Yesterday I shared this gist:

{% twitter 1175878924926095360 %}

And I planned to expand on it today based on some assumptions I had.

{% twitter 1176126201234169860 %}

By playing around in GHCi I found out that my assumption was wrong.

![you are wrong meme](https://thepracticaldev.s3.amazonaws.com/i/4xth2mphqqvkptf1eir7.jpg)

So I did a bit of digging, by digging I mean [Hoogling](https://hoogle.haskell.org) the functions and checking their sources in Hackage, to understand why.

I found some interesting things.

Let's check [again](https://twitter.com/gillchristian/status/1173326782700953601?s=20) how the operator `(<*)` works.

```haskell
(<*) :: Applicative f => f a -> f b -> f a
```

As it is always the case in Haskell, the signature says a lot. It looks like it takes two applicatives and returns the first one.

```haskell
Just 1 <* Just 2 -- Just 1
```

And yes, that's right. But there's more...

It does not only return the first one discarting the second. Instead it "runs" both and returns the first one. How do we know it "runs" both? Because the semantic of such applicative (in this case Maybe) are _respected_:

```haskell
Nothing <* Just 1  -- Nothing
Just 1  <* Nothing -- Nothing
```

And that is the difference with `const`.

```haskell
Just 1  `const` Just 2  -- Just 1
Just 1  `const` Nothing -- Just 1
Nothing `const` Just 1  -- Nothing
```

When I said that `(<*)` is the "lifted" version of `const` I didn't mean _lifted_ in the Haskell sence, I meant _lifted_ as in the function was used in the context of an applicative. Well I guess that's kind of what _lifted_ means, so let's try again. What I meant is that the signature was "the same" but in the applicative context (same semantics, always returning the first argument and discarting the second).

Turns out, `(<*)` is actually the "lifted" version of `const` (in the Haskell sense). Oh, and that's exactly the implementation in `base`.

```haskell
class Functor f => Applicative f where
    -- ...

    -- | Sequence actions, discarding the value of the second argument.
    (<*) :: f a -> f b -> f a
    (<*) = liftA2 const
```

<figcaption>

<a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#%3C%2A" target="_blank">See source in Hackage</a>

</figcaption>

So what I was wrong about? 🤔

I assumed that if you _lifted_ `const` it would still behave as the good ol' const.

```haskell
constA = liftA2 const

Just 1  `constA` Just 2  -- Just 1
Just 1  `constA` Nothing -- Just 1
Nothing `constA` Just 1  -- Nothing
```

Well, as we saw already, it doesn't. As I said it _respects_ the semantics of the applicative.


```haskell
constA = liftA2 const

Just 1  `constA` Just 2  -- Just 1
Just 1  `constA` Nothing -- Nothing
Nothing `constA` Just 1  -- Nothing
```

Because that is the whole point of `liftA2`.

\* to be continued (whit a deeper look into `liftA2`).

_P.S. Yeah I used a "lifting" 🏋️ picture in a post about lifting. Sorry._