我在Haskell中探索类型系列,尝试建立我可以定义的类型级函数的复杂性。我想定义一个封闭的类型级版本mod
,如下所示:
{-# 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
然而,编译器(GHC 7.10.2)拒绝这一点,因为第一个等式中的约束是不允许的。价值级别的警卫如何转换为类型级别?这在Haskell目前是否可行?
答案 0 :(得分:2)
不是答案(我认为甚至还没有答案),但为了其他人(像我一样)的利益,试图在评论中回溯OP的步骤。以下编译,但快速使用它会导致堆栈溢出。
{-# 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
原因是If
本身只是一个普通的类型族,类型族的行为首先是在使用右侧的类型参数之前扩展它们的类型参数(在某种意义上是渴望的)。在这种情况下的不幸结果是即使Mod (m - n) n
为假,n <=? m
也会扩展,因此堆栈溢出。
出于完全相同的原因,Data.Type.Bool
中的逻辑运算符不会短路。鉴于
type family Bottom :: Bool where Bottom = Bottom
我们可以看到False && Bottom
和True || Bottom
都挂起。
如果OP只对具有所需行为的类型系列感兴趣(并且不仅仅是在类型系列中具有保护的更普遍的问题),那么 是一种表达{{1>的方式以一种终止的方式:
Mod