GithubHelp home page GithubHelp logo

Comments (7)

DestyNova avatar DestyNova commented on July 3, 2024 2

Regarding suggestions to make it easier to understand the output of LH, could LH perhaps give a specific hint when it can't prove that some constraints hold in similar situations?

For example, maybe an Elm-style error message like:

(Line xx, col yy) In the function call: f y xs,
I couldn't prove that the return value satisfies this constraint: {VV: a | y <= VV}.
The (inferred/actual) type signature of f looks like this: (...monomorphic inferred signature...) but I expected to see: (...signature that would allow the proof to continue...)
Hint: It may help to give f an explicit polymorphic type signature.

from liquidhaskell-tutorial.

ranjitjhala avatar ranjitjhala commented on July 3, 2024 1

from liquidhaskell-tutorial.

DestyNova avatar DestyNova commented on July 3, 2024

I also tried removing the type signature for insert, and expected the following definition of insertSort' to be invalid:

insert             :: (Ord a) => a -> IncList a -> IncList a
insert y Emp       = y :< Emp
insert y (x :< xs)
  | y <= x         = y :< x :< xs
  | otherwise      = x :< insert y xs

insertSort'     :: (Ord a) => [a] -> IncList a
insertSort' = foldr f b
  where
    f = insert
    b = Emp

However, it typechecked with no problems. Why is this legal, but hoisting the definition of insert into the insertSort' function's where block is rejected (unless a type signature is added to f)?

Apologies for the basic questions, I'm just keen to understand this. 😀

from liquidhaskell-tutorial.

ranjitjhala avatar ranjitjhala commented on July 3, 2024

from liquidhaskell-tutorial.

DestyNova avatar DestyNova commented on July 3, 2024

Thanks for sharing that draft @ranjitjhala, it helped to understand some of the cleverness that was going on (namely, that the use of polymorphic types allows LH to conclude that insert cannot return an (Ord a) => IncList a with larger or smaller values than those passed to it in its arguments.... but that a concrete type like IncList Int would not permit such a guarantee).

However I'm still a bit confused about a couple of points:

  1. If the type signature for the f is omitted, then GHC must infer one. Surely it can't replace the a with Int because the error still appears when I remove the test code that calls insertSort' with a list of integers. So what does it infer? (I tried unsuccessfully to find out in GHCi.)
  2. If the type signature for the insert (in "top-level" file scope) is removed, the error doesn't appear:
-- insert :: (Ord a) => a -> IncList a -> IncList a -- GHC still infers this
insert y Emp       = y :< Emp
insert y (x :< xs)
  | y <= x         = y :< x :< xs
  | otherwise      = x :< insert y xs

insertSort'     :: (Ord a) => [a] -> IncList a
insertSort' = foldr f b
  where
    f = insert
    b = Emp

I have to admit not being familiar with GHC's concept of existential quantification. Could it be that, at the top-level, a function without a type signature is assumed to be valid "forall" inputs, but moving the definition into the where clause of insertSort' causes it to be inferred as potentially a partial function, which then causes LH to not treat it as polymorphic?

I've tested that GHC infers the equivalent type signature for insert when one hasn't been defined. But I can't quite figure out how to test what it thinks f's signature would be when defined inside insertSort'.

from liquidhaskell-tutorial.

LPTK avatar LPTK commented on July 3, 2024

@ranjitjhala Am I correct in understanding that the problem here is the lack of polymorphic recursion in local bindings?

I know that while GHC can infer polymorphic types, it will restrict itself to monomorphic recursion. But I take it that Liquid Haskell can force instantiation of the GHC-inferred types in recursive calls for its own refinement purposes, getting polymorphic recursion this way.

What's not clear to me is why GHC doesn't generalize local local bindings. I thought let generalization was only disabled when certain GHC options were enabled (like GADTs).

from liquidhaskell-tutorial.

ranjitjhala avatar ranjitjhala commented on July 3, 2024

Hi @LPTK -- yes that's exactly it. For non-top-level bindings GHC doesn't "generalize" the inferred type, perhaps because (I'm guessing) there is no need to really. For top-level binders you want to generalize otherwise the function is basically useless...

My hunch is that this paper probably articulates the rationale for why local binders are not generalized:

https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tldi10-vytiniotis.pdf

from liquidhaskell-tutorial.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.