2016-09-18 4 views
2

GHC 8.0.1では、タイプレベルのリストに対してタイプレベルLengthを実装しようとしています。無効なネスト型ファミリアプリケーション(これを許可するにはUndecidableInstancesを使用してください)

{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies #-} 

data Nat = Z | S Nat 

type family Length (l :: [*]) :: Nat where 
    Length '[] = Z 
    Length (_ ': as) = S (Length as)  

しかし、私はTypeLitsを使用している場合、それはコンパイルされません:それはコンパイル

import GHC.TypeLits 

type family Length (l :: [*]) :: Nat where 
    Length '[] = 0 
    Length (_ ': as) = 1 + Length as 

をコンパイラが次のエラー得られます。

• Illegal nested type family application ‘1 + Length as’ 
    (Use UndecidableInstances to permit this) 
• In the equations for closed type family ‘Length1’ 
    In the type family declaration for ‘Length1’ 
+3

「UndecidableInstances」をオンにしてください。 GHCの終了チェッカーは特に洗練されていません。別のタイプのファミリーのRHS上のタイプファミリーを使用することは、禁止されているものの1つです。 –

答えて

4

をあなたはオンにする必要がありますUndecideableInstances。この拡張機能は、コンパイルが常に終了することを保証する一連の制限を解除します。これらのうちの1つはタイプファミリーと関係しています。あなたの最初の例では、RHSの外側の項は実際の型であり、型関数への別の呼び出しではありません。一方、2番目の例では、RHSは完全に型関数(+)(同じ名前の値レベル関数と誤解されてはいけません)への呼び出しです。

GHCは、あなたが書いたことを終わらせることができないので文句を言う。実際には、それほど変わっていません。

type family Length (l :: [*]) :: Nat where 
    Length '[] = 0 
    Length (a ': as) = 1 + Length (a ': as) 
+1

公正であるためには、あなたの例を非終端にするのは '+'の呼び出しではなく、それは非小引数の 'Length'への再帰呼び出しです。 GHCはネストされた型のファミリを拒否します。なぜなら、 '+'は相互に反復的に '' Length''を非終了を生成するように呼び出すわけではないからです。 GHCには非常にスマートな終了チェッカーが搭載されていないからです。より良い(read:_more complex_)システムはOPの定義を受け入れますが、あなたのものは受け入れません。 –

+0

Ah。私はこれまで深く熟考していませんでした。あなたのコメントは確かに役立ちます。 – Alec

関連する問題