2
votes

So here is my goofy sandbox to play with Applicatives in PureScript

module Main where

import Debug.Trace

data Foo a
   = Foo a

instance showFoo :: (Show a) => Show (Foo a) where
  show (Foo a) = "I pity da (Foo " ++ (show a) ++ ")"

instance functorFoo :: Functor Foo where
  (<$>) f (Foo a) = Foo (f a)

instance applyFoo :: Apply Foo where
  (<*>) (Foo a) (Foo b) = Foo (a b)

m :: Number -> Number -> Number -> Number
m x y z = x * y - z

main = trace <<< show $ m <$> Foo 14
                          <*> Foo 2
                          <*> Foo 5

The above works fine, but if I remove:

m :: Number -> Number -> Number -> Number

it does not compile

Error at pure.purs line 18, column 1: 
Error in declaration m
No instance found for Prelude.Num u1150

However (+) and (-) are both of type

forall a. (Prelude.Num a) => a -> a -> a

Why can't Number be inferred?


The reality is that when learning PureScript and coming from a dynamic language (JavaScript), I run into type errors frequently. Developing skills in diagnosing and understanding these errors is challenging without a grasp of when inference can occur and when it can't. Otherwise I will have to write types every single time in order to feel confident in my code (lameness).

1

1 Answers

3
votes

This is because at the moment the compiler can't infer typeclass constraints, and as you noted the arithmetic operators are all defined in the Num typeclass.

The type that would be inferred for m (if the compiler could) would be something like:

m :: forall a. (Num a) => a -> a -> a -> a

On your second point typing top level declarations is considered good style anyway, as it helps to document your code: see here for a fuller explanation.