Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell GHC重写pragma是否必须保持类型?_Haskell_Ghc_Pragma - Fatal编程技术网

Haskell GHC重写pragma是否必须保持类型?

Haskell GHC重写pragma是否必须保持类型?,haskell,ghc,pragma,Haskell,Ghc,Pragma,假设我有一种短期语言: import Data.Void (Void,absurd) 如果我想组合术语c Void和术语c Int类型的术语,那应该是可能的,因为我保证第一个术语不包含任何变量。因此,我可以编写以下函数: data Term c v where Var :: v -> Term c v Con :: c -> [Term c v] -> Term c v 然而,如果真的运行这个函数,那将是一个耻辱,因为我知道事实上它实际上

假设我有一种短期语言:

import Data.Void (Void,absurd)
如果我想组合
术语c Void
术语c Int
类型的术语,那应该是可能的,因为我保证第一个术语不包含任何变量。因此,我可以编写以下函数:

data Term c v where
  Var :: v               -> Term c v
  Con :: c -> [Term c v] -> Term c v
然而,如果真的运行这个函数,那将是一个耻辱,因为我知道事实上它实际上并没有改变任何东西。添加以下pragma是否安全:

castVar :: Term c Void -> Term c v
castVar (Var i   ) = absurd i
castVar (Con x xs) = Con x (map castVar xs)
这真的能达到预期的效果吗


有更好的方法吗?

不,这样不行。重写规则仅在类型检查时应用。在这种情况下,只有运行
castVar::Term c Void->Term c Void
,规则才会触发,这没有多大帮助。(有关重写规则的更多信息,请参阅)

您想要的是强制该类型。这样做是安全的,因为您知道
术语
中没有
Void
。您可以通过导入
Unsafe.concure
castVar=unsafeccerce
或使
Term
成为
Functor
的一个实例(您可以为这个简单版本派生它)并使用
unsafeVacuous
from
Data.Void.Unsafe

{-# NOINLINE castVar #-}
{-# RULES "castVar/id" forall x. castVar x = x; #-}