Skip to content

Unannotated recursive local binding: Cannot unify 'Int -> Int' with 'Int -> Int' #680

Open

Description

@i-am-the-slime

A local binding that has no type signature and refers to itself inside a lambda passed to another function is rejected by Iris with a CannotUnify error between two identical types. purs 0.15.16 accepts the same code.

Repro

module Main where

import Prelude

call :: forall f. (Unit -> f) -> f
call k = k unit

f :: Int -> Int
f = go
  where
  go = call \_ -> go

Iris 0.1.15

Error! · [CannotUnify] · src/Main.purs:11:3
  │
  • Cannot unify 'Int -> Int' with 'Int -> Int'
  │
  │     go = call \_ -> go
  │     ╰─────────────────

purs 0.15.16 (via spago) builds the same module successfully.

What changes the result

  • Adding a signature to the local binding (go :: Int -> Int) makes Iris accept it.
  • The same binding at top level, without a signature, is accepted.
  • let inside do fails the same way as where.
  • Rank-N is not required: call :: forall f. (forall x. x -> f) -> f fails identically.

Where it shows up

The playwright package (registry package set) uses this pattern in three places, so any project depending on it fails to build with Iris. For example, in Playwright/Dialog.purs:

type' :: Dialog -> Effect DialogType
type' = map convert <<< type''
  where
    type'' = effCall "type" \_ -> type''

There, Iris reports Cannot unify 'Function Dialog (Effect String)' with 'Function Dialog (Effect String)'.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions