2017-02-20 10 views
4

私が最初に深刻なcriticism on -XUndecidableInstancesを読む時までに、私はすでにそれに完全に慣れていました。それは単にという迷惑な制限の削除であると見なされます。Haskell98はコンパイラの実装を容易にする必要があります。undecidableインスタンスは実際にコンパイラをハングアップさせることができますか?

実際、私は、決定不能なインスタンスが必要だったアプリケーションがたくさん出てきましたが、実際にはそれらがundecidabilityに関係する問題を引き起こしていませんでした。これは実際に国連決定論です:!まあ、これは明らかには、任意の適切なGroupインスタンスによってをオーバーラップされますので、決定不能が私たちの心配の少なくともです - ルカの例では、

class Group g where 
    (%) :: g -> g -> g 
    ... 
instance Num g => Group g where 
    ... 

全く異なる理由で問題があります

しかし、私の頭の後ろには、「判読不能なインスタンスがコンパイラーをハングアップする可能性がある」ということがありました。

this challenge on CodeGolf.SEを読むと、コンパイラを無期限にハングするコードを尋ねられました。うーん、うまくいかないインスタンスの仕事のように聞こえるよね?

私は彼らにそれをさせることができません。少なくともGHC-7.10から時間がないの、次のコンパイル、:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 
class C y 
instance C y => C y 
main = return() 

私もクラスメソッドを使用することができ、そして、彼らは唯一のランタイムでループを引き起こします:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 
class C y where y::y 
instance C y => C y where y=z 
z :: C y=>y; z=y 
main = print (y :: Int) 

しかしランタイムループは珍しいことではありません.Haskell98でこれらを簡単にコーディングすることができます。

Iはまた、異なる試み、以下そのような再度

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-} 
data A x=A 
data B x=B 
class C y 
instance C (A x) => C (B x) 
instance C (B x) => C (A x) 

として直接ループ、コンパイル時に問題はありません。

したがって、実際には、コンパイラは、決定不可能な型クラスのインスタンスを解決するためにハングする必要がありますか?

+0

「Int」が 'C'のインスタンスであるかどうかをコンパイラが判断するようにする必要があるかもしれません。 – immibis

答えて

10

私は実際にコンパイラを掛けたことはないと思います。あなたの最初の例を変更することで、オーバーフローすることがあります。何度もキャッシュが行われているように見えるので、ユニークな制約の無限のシーケンスを要求する必要があります。私たちは、あなたが本当にしたい場合、それがハングアップするために得ることができる方法を説明します

• Reduction stack overflow; size = 201 
    When simplifying the following type: 
    C (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
    Use -freduction-depth=0 to disable this check 
    (any upper bound you could choose might fail unpredictably with 
    minor updates to GHC, so disabling the check is recommended if 
    you're sure that type checking should terminate) 

を与える

data A x = A deriving (Show) 
class C y where get :: y 
instance (C (A (A a))) => C (A a) where 
    get = A 

main = print (get :: A()) 

。私の推測では、これがなくてもハングアップすることができれば、バグが見つかりました。

私はGHCで働く誰かから聞きたいです。

「削減スタックオーバーフロー」を取得する最も簡単な方法は、タイプファミリを使用している
6

type family Loop where 
    Loop = Loop 

foo :: Loop 
foo = True 

私は実際に現在のGHCでコンパイルをループを取得するための直接的な方法を知りません。私はGHC 7で数回ループを取得することを思い出します。しかし、私は再現可能な細部のものを覚えています:

data T where 
    T :: forall (t :: T). T 

しかしこれは修正されています。

2

私の驚いたことに、UndecidableInstancesは、特定のGHCバージョンを実際にハングアップする可能性があります。ここでは私のためにそれをやった数行のコードは次のとおりです。

(直接ではなく ghc main.hs)このコードは、GHC 8.2.1

@luquiが述べたように、無期限にハングアップするライブラリの一部としてコンパイル

{-# LANGUAGE FlexibleInstances  #-} 
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE TypeFamilies   #-} 
{-# LANGUAGE UndecidableInstances #-} 
module Nested where 

class Nested r ix where 

type family Lower ix :: * 

data LN 

instance Nested LN (Lower ix) => Nested LN ix where 

data L 

instance Nested LN ix => Nested L ix where 

、それは、このようなことが報告されているので、これは、バグのように見えるん:https://ghc.haskell.org/trac/ghc/ticket/14402

編集:それはすでにGHCの現在の開発バージョンで修正された、実際にバグであることが判明しました。

関連する問題