 # On Partial and Composition

Hi!

I’m using seriously Purescript for a personal project since few days, and I’m playing with the language. I had a question when I started Firebase interop. To give a little bit of context, when using Firebase Firestore, you can have timestamp, which are server timestamps, encoded in Firebase Timestamp (a native JS object) which can be turned into a Date.
I managed a lot of things with Timestamps, and I wanted to make a function to convert them from Timestamp to Date. I managed to do it without too much pain, but here’s come the question.
At first, I wrote this:

For the foreign.

``````foreign import foreignTimestampToDate :: Timestamp -> JSDate
``````

And the code:

``````timestampToDate :: Timestamp -> Date
timestampToDate =
unsafePartial
<<< fromJust
<<< JSDate.toDate
<<< foreignTimestampToDate
``````

The compiler told me it’s an error, because of something Partial. I didn’t get the error, and tried this:

``````timestampToDate :: Timestamp -> Date
timestampToDate date =
unsafePartial
\$ fromJust
\$ JSDate.toDate
\$ foreignTimestampToDate date
``````

And this code is working perfectly.

What is the difference between the two functions? I don’t understand the difference.

1 Like

Yes, this has bitten me before too, however we can see the difference on the REPL:

``````> import Prelude ((<<<), (\$))
> import Data.Maybe (fromJust)
> import Partial.Unsafe (unsafePartial)
> :t unsafePartial <<< fromJust
forall t2. Partial => Maybe (Partial => t2) -> t2
> :t unsafePartial \$ fromJust
forall t4. Maybe t4 -> t4
``````

So it’s clear you want the latter. Why the constraints are solved differently by the type checker between (<<<) and (\$) I’m not quite sure…

1 Like

Constraints in PureScript are elaborated to function arguments and applications. When something has a `Partial => ...` signature, it’s like adding another unit-like argument to the function, where a `Partial` argument (dictionary) is passed in at the call-site. The signature of `unsafePartial` takes a function accepting an implicit `Partial` constraint, and explicitly discharges it. That is, it supplies an argument/dictionary for the constraint, giving back the underlying `a` value.

``````unsafePartial :: forall a. (Partial => a) -> a
``````

A desugared version of that signature might be something like:

``````data PartialDict = PartialDict

unsafePartial :: forall a. (PartialDict -> a) -> a
``````

Note that the `Partial` constraint has been replaced with a dictionary, and instead of `=>` we have an explicit `->`. The compiler does a translation like this automatically. The implementation essentially then becomes something equivalent to:

``````unsafePartial :: forall a. (PartialDict -> a) -> a
unsafePartial fn = fn PartialDict
``````

Your particular example can be simplified to something like:

``````bad :: forall a. a -> a
bad = unsafePartial <<< fromJust <<< Just

good :: forall a. a -> a
good a = unsafePartial (fromJust (Just a))
``````

Now, lets look at the signature of `fromJust`:

``````fromJust :: forall a. Partial => Maybe a -> a
``````

If we apply a similar translation as above:

``````fromJust :: forall a. PartialDict -> Maybe a -> a
``````

We see that `fromJust` is actually a function of two arguments to the compiler. However, function composition only works on a single argument. Lets breakdown the `bad` implementation.

1. It first lifts a value into `Maybe a` via the `Just :: forall a. a -> Maybe a` constructor.
2. It then calls `fromJust :: forall a. Partial => Maybe a -> a` on that value.
3. It then attempts to remove a `Partial` constraint via `unsafePartial :: forall a. (Partial => a) -> a`.

If you look at the signatures of 1 and 2, you’ll see that in order to feed a `Maybe a` value into `fromJust`, we must first apply a `Partial` dictionary. If we were to desugar that:

``````fromJust somePartialDict <<< Just
``````

Where `somePartialDict` is a free variable. That is, we eagerly need to provide a dictionary for `Partial` in order to even build our function composition. The type and desugaring of this expression is:

``````c1 :: forall a. PartialDict -> a -> a
c1 somePartialDict = fromJust somePartialDict <<< Just
``````

`bad` is failing because there’s nothing in scope to provide for `somePartialDict`. There’s more to it though, and why this wouldn’t be type correct. Just like `fromJust`, we have a two-argument function again. At this point we are feeding in an `a` value to `unsafePartial` (since we’ve already called `fromJust`), when it actually needs a function that takes `Partial => a`. There are a few alternative solutions:

The `good` variant above, which desugars to:

``````good a = unsafePartial (\somePartialDict -> fromJust somePartialDict (Just a))
``````

The compiler can look at the type unsafePartial, and know that it should elaborate the argument to take a constraint.

You can also do:

``````good2 = unsafePartial (fromJust <<< Just)
``````

Which elaborates to something similar to the `c1` example above.

And a third variant would be to change the signature of `fromJust`. Part of the problem is that a `Partial` dictionary must be provided first. Instead you could write:

``````fromJust' :: forall a. Maybe a -> (Partial => a)
``````

and then your original composition would work.

I’d recommend trying these all out on `try.purescript.org` and look at the generated JS source to see how the compiler is elaborating the code.

5 Likes

(Posting this before I have read what Nate posted, but I think it might complement his)

To give some more intuition as to how the types work, I think it’s useful to write a compose that does work for the case

``````myCompose2 :: forall a b c. ((Partial => b) -> c) -> (Partial => a -> b) -> (a -> c)
myCompose2 f g x = f (g x)

myCompose1 :: forall a b c. (b -> c) -> (a -> b) -> (a -> c)
myCompose1 f g x = f (g x)

-- using myCompose1 won't work
func :: forall x. Maybe x -> x
func = unsafePartial `myCompose2` fromJust
``````

Looking at the compiler output, we can see the runtime representations of each compose are different and therefore not interchangeable (although just because they look different doesn’t mean they are, not sure how to prove it):

``````var myCompose2 = function (f) {
return function (g) {
return function (x) {
return f(function (dictPartial) {
return g()(x);
});
};
};
};

var myCompose1 = function (f) {
return function (g) {
return function (x) {
return f(g(x));
};
};
};

``````
1 Like

Wow, thank you very much for your answers. I wasn’t expecting so much. It’s awesome.

I’d recommend trying these all out on `try.purescript.org` and look at the generated JS source to see how the compiler is elaborating the code.

That’s effectively a good idea I didn’t thought about. I’ll play a little bit with this and try to see how the compiler is generating JS.

1 Like