I am encoding (as an assumption) the functor identity law like so:
...
import qualified Prelude ()
...
{-@ class Functor f where
fmap :: forall a b. (a -> b) -> (f a -> f b) @-}
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
-- identity function
{-@ id :: forall a . x : a -> {y : a | x = y} @-}
id :: forall a . a -> a
id x = x
-- functor law: mapping with identity is identity
{-@ assume
fmap_id :: forall f a . Functor f => x : f a ->
{fmap id x = id x} @-}
fmap_id :: Functor f => f a -> ()
fmap_id _ = ()
I can't see anything wrong with this formulation, yet I get this error from LH:
src/Category/Functor/LH.hs:45:16: error:
• Illegal type specification for `Category.Functor.LH.fmap_id`
Category.Functor.LH.fmap_id :: forall f a .
(Functor<[]> f) =>
x:f a -> {VV : () | Category.Functor.LH.fmap Category.Functor.LH.id x == Category.Functor.LH.id x}
Sort Error in Refinement: {VV : Tuple | Category.Functor.LH.fmap Category.Functor.LH.id x == Category.Functor.LH.id x}
Unbound symbol Category.Functor.LH.fmap --- perhaps you meant: Category.Functor.LH.C:Functor ?
•
|
45 | fmap_id :: forall f a . Functor f => x : f a ->
|
What am I doing wrong? My goal is to formulate this point-free with extensionality, but at least this point-wise formulation should work first.
Configuration:
- GHC version: 8.10.1
- Cabal version: 3.2.0.0
- Liquid Haskell version: 0.8.10.2
Support for typeclasses is not yet supported in the official release of Liquid Haskell (although it is almost ready to merge). For now, you can use this fork which implements typeclass support. After recursively cloning the repository, you can install the forked version with:
We define
Functor
and its laws (in theVFunctor
subclass) inliquid-base/liquid-base/src/Data/Functor/Classes.hs
as follows. Notice that you can specify refinements on the typeclass methods directly.You can run the forked version of Liquid Haskell on the typeclass definitions with:
We create a verified
Maybe
instance inliquid-base/liquid-base/src/Data/Maybe/Functor.hs
with:You can run Liquid Haskell on the
Maybe
instance to verify that it satisfies the required laws: