Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem typing a let expression #4527

Open
desfreng opened this issue Jan 3, 2024 · 1 comment
Open

Problem typing a let expression #4527

desfreng opened this issue Jan 3, 2024 · 1 comment

Comments

@desfreng
Copy link

desfreng commented Jan 3, 2024

Description

Hi ! I've been playing around with PureScript's typing system and I've come across an example where the compiler's behaviour doesn't seem consistent.

In my experiments and as mentioned in ticket #4498, PureScript does not generalise let expressions. So why is the following code accepted by the compiler? The reasons why I think this code should not be accepted are in the comments to the following code.

module Main where

import Prelude (class Show, Unit, discard, show, (<>))
import Effect (Effect)
import Effect.Console (log)

data List a = Nil | Cons a (List a)

instance (Show a) => Show (List a) where
  show (Nil) = "Nil"
  show (Cons hd tl) = "(Cons " <> show hd <> " " <> show tl <> ")"

main :: Effect Unit
main = let x = Nil in -- x :: List τ, with τ unknown at this point
  do
    (let y = Cons "a" x in log (show y)) -- Here we find that τ = String, so x :: List String
    (let z = Cons true x in log (show z)) -- Boolean /= String, so why no error is repported here ?

The error is correctly emitted when the arity of the List type is modified :

module Main where

import Prelude (class Show, Unit, discard, show, (<>))
import Effect (Effect)
import Effect.Console (log)

data List a b = Nil a | Cons b (List a b)

instance (Show a, Show b) => Show (List a b) where
  show (Nil x) = "(Nil " <> show x <> ")"
  show (Cons hd tl) = "(Cons " <> show hd <> " " <> show tl <> ")"

main :: Effect Unit
main = let x = Nil 1 in -- x :: List Int τ, with τ unknown at this point
  do
    (let y = Cons "a" x in log (show y)) -- Here we find that τ = String, so x :: List Int String
    (let z = Cons true x in log (show z)) -- Boolean /= String, so we GET an error repported here.

To Reproduce

To reproduce this problem, simply copy-paste each of the examples into the Main.purs file generated by spago init, then call spago build.
You can also use try.purescript.org :

Expected behavior

I expected the compiler to behave consistently, regardless of the arity of the List type introduced. That is, an error would be returned at the point explained in the comments in the first code snippet.

PureScript version

v0.15.13 (with try.purescript.org) and v0.15.12 (on my computer).

@natefaubion
Copy link
Contributor

Probably #3874 I don't know if it's generalization so much as Nil is an identifier with a known type so it just accepts it's type as-is (lazy instantiation).

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

No branches or pull requests

2 participants