Finding the type of an expression in a local binding

Viewed 63

Is there a way I can find the type of shift in the code below by rewriting the instance below? Is the reason I cannot find its type when I try to call it below because it is a local binding (in the where construct)?

class CoMonad m where
  extract :: m a -> a
  (<<=) :: (m a -> b) -> m a -> m b
instance (Monoid s) => CoMonad ((->) s) where
  extract = ($ mempty)
  f <<= r = \ t -> (f . shift t) r
     where shift t rr = \ s -> rr (s <> t)

:t shift

<interactive>:1:1: error: Variable not in scope: shift

    
1 Answers

One possibility is giving shift an incomplete signature with a wildcard:

class CoMonad m where
  extract :: m a -> a
  (<<=) :: (m a -> b) -> m a -> m b
instance (Monoid s) => CoMonad ((->) s) where
  extract = ($ mempty)
  f <<= r = \ t -> (f . shift t) r
     where
     shift :: _ 
     shift t rr = \ s -> rr (s <> t)

This will fail to typecheck with an useful error message:

<interactive>:9:15: error:
    • Found type wildcard ‘_’ standing for ‘s -> (s -> t) -> s -> t’
      Where: ‘t’ is a rigid type variable bound by
               the inferred type of shift :: s -> (s -> t) -> s -> t
               at <interactive>:10:6-36
             ‘s’ is a rigid type variable bound by
               the instance declaration
               at <interactive>:5:10-39
      To use the inferred type, enable PartialTypeSignatures
    • In the type signature: shift :: _
      In an equation for ‘<<=’:
          f <<= r
            = ...
            where
                ...
      In the instance declaration for ‘CoMonad ((->) s)’
    • Relevant bindings include
        r :: s -> a (bound at <interactive>:7:9)
        f :: (s -> a) -> b (bound at <interactive>:7:3)
        (<<=) :: ((s -> a) -> b) -> (s -> a) -> s -> b
          (bound at <interactive>:7:5)

As Jon Purdy reminds us, the partial signature can also be added inline, as a type annotation:

(\ t -> (f . (shift :: _)) r

If you hadn't actually added the local binding yet, a typed hole (_shift in the example below) would, in a similar way, give you the inferred type for whatever is missing.

\ t -> (f . _shift) r
Related