2016-05-31 19 views
7

Haskell'deki tür aileleri araştırıyorum, tanımlayabileceğim tip düzeyindeki işlevlerin karmaşıklığını oluşturmaya çalışıyorum. Ben şöyle bir şey mod kapalı tip düzeyindeki sürümü tanımlamak istiyorum: İlk denklemde kısıt yasaktır olarakTip aile örneklerindeki kısıtlamalar

{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, UndecidableInstances #-} 
import GHC.TypeLits 

type family Mod (m :: Nat) (n :: Nat) :: Nat where 
    n <= m => Mod m n = Mod (m - n) n 
    Mod m n = m 

Ancak derleyici (GHC 7.10.2), bu reddeder. Değer seviyesindeki gardiyanlar tip seviyesine nasıl aktarılır? Bu şu anda Haskell'de mümkün mü?

+0

Belki bir "If" tipi düzey işlevi var mı? Sanırım bir yerlerde kullanılmış olduğunu gördüm, ama ben bir kütüphane uzmanı değilim ... – chi

+0

Teşekkürler, kesinlikle haklısınız, eğer [Data.Type.Bool] 'da bulunuyorsanız (https://hackage.haskell.org /package/base/docs/Data-Type-Bool.html). –

+0

Bunu takiben, başarılı bir şekilde derlenmiş tip-seviyesi 'If' kullanılarak' Mod' yeniden yazmayı başardım. Ancak, 'Mod m n' formunun bir terimini azaltma girişimi, yığın taşması istisnasıyla sonuçlandı. _-Freduction-depth_ seçeneğinin ayarlanması bana GHC'nin, bu mümkün olmayacağının farkında olmadan, ifadenin 'm-n 'bölümünü genişletmeye öncelik verdiğini gösterdi. Davranışın daha fazlasını anlamak için _DataKinds_ uzantısına daha fazla bakmak zorunda kalacağım. –

cevap

1

Cevap değil (henüz bir tane bile mümkün olduğunu düşünmüyorum), fakat diğer kişilerin (benim gibi) faydaları için OP'leri yorumlarda tekrar gözden geçirmeye çalışıyorum. Aşağıdaki derlemeler, ancak bunu kullanarak hızlı bir şekilde yığın taşmasıyla sonuçlanır.

{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, UndecidableInstances #-} 
import GHC.TypeLits 
import Data.Type.Bool 

type family Mod (m :: Nat) (n :: Nat) :: Nat where 
    Mod m n = If (n <=? m) (Mod (m - n) n) m 

nedeni If kendisi sıradan bir tip aile ve tip-ailelerin davranış sağ tarafta olanlar kullanmadan önce tip argümanları (bir anlamda istekli) genişleterek başlamaktır olmasıdır. Bu durumdaki talihsiz sonuç, n <=? m yanlış olsa bile, Mod (m - n) n'un genişletilmesi ve dolayısıyla yığının taşmasıdır.

Tam olarak aynı nedenle, Data.Type.Bool'daki mantıksal işleçler kısa devre yapmaz. Biz False && Bottom ve True || Bottom hem asmak görebilirsiniz

type family Bottom :: Bool where Bottom = Bottom 

Verilen.

DÜZENLEME

OP orada yılında Mod ifade etmenin bir yoludur olan gerekli davranışı ile bir tür aile içinde sadece ilgi (ve tip ailelerde korumaları sahip değil, sadece daha genel bir sorun) 'dir Ne olur ne

bir sonlandırma yolu:

{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, UndecidableInstances #-} 
import GHC.TypeLits 

type Mod m n = Mod1 m n 0 m 

type family Mod1 (m :: Nat) (n :: Nat) (c :: Nat) (acc :: Nat) :: Nat where 
    Mod1 m n n acc = Mod1 m n 0 m 
    Mod1 0 n c acc = acc 
    Mod1 m n c acc = Mod1 (m - 1) n (c + 1) acc