GHCi ignores type signature

后端 未结 2 621
梦谈多话
梦谈多话 2021-02-12 13:16
Prelude> let myprint = putStrLn . show
Prelude> :t myprint
myprint :: () -> IO ()

OK, nothing too unusual here. Just GHCi type defaulting rule

相关标签:
2条回答
  • 2021-02-12 14:03

    We can do the following, with monomorphism restriction on:

    >let myprint :: Show x => x -> IO (); myprint = putStrLn . show
    >:t myprint
    myprint :: Show x => x -> IO ()
    

    This is not the same as let myprint = putStrLn . show :: Show x => x -> IO (). In the former case we have a binding with a type signature, in the latter case we a have a let binding with a type annotation inside the right hand side. Monomorphism checks top-level type signatures, but not local annotations.

    0 讨论(0)
  • 2021-02-12 14:21

    Adding a type annotation to an expression as in

    e :: type
    

    makes the compiler check that e has that type, as well as use that type to drive type variables instantiation and instance selection. However, if the type is polymorphic it can still be instantiated later on. Consider e.g.

    (id :: a -> a) "hello"
    

    Above, a will be instantiated to String, despite my annotation. Further,

    foo :: Int -> Int
    foo = (id :: a -> a)
    

    will make a to be instantiated to Int later on. The above id annotation does not give any information to GHC: it already knows that id has that type. We could remove it without affecting the type checking at all. That is, the expressions id and id :: a->a are not only dynamically equivalent, but also statically such.

    Similarly, the expressions

    putStrLn . show
    

    and

    (putStrLn . show) :: Show x => x -> IO ()
    

    are statically equivalent: we are just annotating the code with the type GHC can infer. In other words, we are not providing any information to GHC it does not already know.

    After the annotation is type checked, GHC can then instantiate x further. The monomorphism restriction does that in your example. To prevent that, use an annotation for the binding you are introducing, not for the expression:

    myprint :: Show x => x -> IO ()
    myprint = (putStrLn . show)
    
    0 讨论(0)
提交回复
热议问题