2

以下に示すコードはコンパイルされます。

data Car p q r = Car {company :: p  
                     , model :: q  
                     , year ::r  
                     } deriving (Show)


tellCar :: (Show a) => Car String String a -> String

「tellCar」でのみ「Showa」を実行する必要があることを思い出させる基本的な原則/規則/ロジックは何ですか?他のオプションはありませんか?そのような原則/慣習/論理を学ぶためのリソースはどこにありますか?

誤ってtellCarで「ShowCar」を取得すると、コンパイル時に次のエラーメッセージが表示されます。

*Main> :load "/home/optimight/baby.hs"  
[1 of 1] Compiling Main             ( /home/optimight/baby.hs, interpreted )  

/home/optimight/baby.hs:96:18:  
    Expecting three more arguments to `Car'  
    In the type signature for `tellCar':  
      tellCar :: Show Car => Car String String a -> String  
Failed, modules loaded: none.  

誤ってtellCarで「Showz」を取得すると、コンパイル時に次のエラーメッセージが表示されます。

*Main> :load "/home/optimight/baby.hs"  
[1 of 1] Compiling Main               ( /home/optimight/baby.hs, interpreted )

/home/optimight/baby.hs:96:1:  
    Ambiguous constraint `Show z'  
      At least one of the forall'd type variables mentioned by the constraint  
      must be reachable from the type after the '=>'  
    In the type signature for `tellCar':  
      tellCar :: Show z => Car String String a -> String  
Failed, modules loaded: none.   

tellCarで誤って「ShowString」を取得すると、コンパイル時に次のエラーメッセージが表示されます。

Prelude> :load "/home/optimight/baby.hs"  
[1 of 1] Compiling Main             ( /home/optimight/baby.hs, interpreted )  

/home/optimight/baby.hs:96:1:  
    Non type-variable argument in the constraint: Show String  
    (Use -XFlexibleContexts to permit this)  
    In the type signature for `tellCar':  
      tellCar :: Show String => Car String String a -> String  
Failed, modules loaded: none.  
4

3 に答える 3

6
于 2012-07-22T13:29:52.773 に答える
5

Main idea: Each constraint listed before the => in the type signature is there to constrain one or more type-variables to the right of the => in the type signature.

Principle: Constraints in type signatures always have a type variable in them somewhere.

Writing Show String => or Show Car => is not helpful, and the error message tells you this is because String has no type-variable (which always start with a lower-case letter). This is because either instance Show String is visible in the scope of tellCar or it is not, and you never need to list fully concrete instances as contraints in the type.

Principle: The constraint you list has to mention at least one of the type variable to the right of the => in the type signature. With LANGUAGE extensions the constraint may mention zero or more extra type variables that only exist on the left of the => in the type signature.

Writing tellCar :: Show z => Car String String a -> String violates this since a is the only type variable on the RHS of the => and Show z does not mention a. This Show z does not constrain the type variable a.

More specifically for your case you write deriving (Show) which auto-generated an instance:

instance (Show p, Show q, Show r) => Show (Car p q r) where
  showsPrec = ...

The auto-generated code only works if there are Show instances for p,q,r. Your specialization to

tellCar :: (Show a) => Car String String a -> String

mentions Car String String a. Using Show on Car String String a in tellCar selects the auto-generated instance for Show (Car p q r) and creates a need for Show String and Show a. The compiler then sees an instance for Show String from the implicitly imported Prelude module leaving only the dangling Show a constraint. This constraint on a infects the type of tellCar.

The resource to learn about the Haskell type system is one of the books on Haskell.

EDIT: The precise part of the Haskell 98 Report covering this seems to section 4.1.3. More background is in "A History of Haskell".

于 2012-07-22T13:42:49.640 に答える
4

関数は型が何になるかわからないため、ポリモーフィック型変数の制約のみが必要になります。また、コンパイラーに、それが機能することを知らせる最小限の情報を提供します。

Show Car =>(またはShow String)は、実際には制約として何も意味しません。コンパイラCar p q rは、Showインスタンスがあることをすでに認識しています。そして、ShowインスタンスCar p q r がなかった場合、コンパイラーはそれをすでに知っているでしょう!したがって、この制約が許可された場合、それは冗長または矛盾することになります。

のエラーShow zはあなたを助けるためにあります。型アノテーションで使用されていない変数を制約しているので、ほぼ間違いなく間違いです。

于 2012-07-22T12:43:36.113 に答える