单例参数的特化
Specialization of singleton parameters
我正在研究单身人士的专业化:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
module Data.Test where
data SingBool (b :: Bool) where
STrue :: SingBool 'True
SFalse :: SingBool 'False
sing :: SingBool b -> Bool
sing SFalse = False
sing STrue = True
{-# SPECIALIZE sing :: SingBool 'False -> Bool #-}
这专门针对以下内容:
singSFalse :: SingBool 'False -> Bool
singSFalse SFalse = False
我希望它生成 singSFalse _ = False
的 RHS。
强制解压缩只是为了满足类型检查器的要求,还是在该模式匹配中涉及实际的运行时开销?我想 GHC 不会丢弃参数上的模式匹配来解释 bottom
,以免增加惰性。但我想在开始通过 Proxy
+ SingI
样式类型 class.
建模之前确定
好的,主要回答我自己的问题:知道 SingBool 'False
只有一个居民不足以让 GHC 摆脱模式匹配,因为我们可以像 singSFalse (error "matched")
这样调用函数,例如底部总是另一个居民。
因此,专业化(例如基于具体 TypeApplication
的内联)在 Haskell(惰性、非-总计)w.r.t。零成本抽象。
但是,通过使用 SingI
-style type class with a proxy (e.g. singByProxy
),我们不会遇到同样的问题:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
module Data.Test where
import GHC.Exts (Proxy#)
class SingIBool (b :: Bool) where
sing :: Proxy# b -> Bool
instance SingIBool 'False where
sing _ = False
instance SingIBool 'True where
sing _ = True
refurbulate :: SingIBool b => Proxy# b -> Int
refurbulate p
| sing p = 0
| otherwise = 1
特化 refurbulate @(Proxy# 'False)
不仅会实现为 const False
,也不会在值级别传递任何 Proxy#
参数,因此它更像是 coerce False :: Proxy# -> Bool
.整洁的!但是,我不会在现实世界中使用单例:(
回顾一下为什么单例失败(为了优化)并输入 classes 工作:
通过特化类型 class 实例,我们了解了 sing
的 RHS,从中我们可以推断出整体性。
通过专门化单例,我们可以知道参数的计算结果,如果计算终止。
知道类型 class 方法 x :: ()
的规范 RHS 比仅仅知道参数 x :: ()
只能计算一个非总值,惰性(例如 Haskell 的)设置。
我正在研究单身人士的专业化:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
module Data.Test where
data SingBool (b :: Bool) where
STrue :: SingBool 'True
SFalse :: SingBool 'False
sing :: SingBool b -> Bool
sing SFalse = False
sing STrue = True
{-# SPECIALIZE sing :: SingBool 'False -> Bool #-}
这专门针对以下内容:
singSFalse :: SingBool 'False -> Bool
singSFalse SFalse = False
我希望它生成 singSFalse _ = False
的 RHS。
强制解压缩只是为了满足类型检查器的要求,还是在该模式匹配中涉及实际的运行时开销?我想 GHC 不会丢弃参数上的模式匹配来解释 bottom
,以免增加惰性。但我想在开始通过 Proxy
+ SingI
样式类型 class.
好的,主要回答我自己的问题:知道 SingBool 'False
只有一个居民不足以让 GHC 摆脱模式匹配,因为我们可以像 singSFalse (error "matched")
这样调用函数,例如底部总是另一个居民。
因此,专业化(例如基于具体 TypeApplication
的内联)在 Haskell(惰性、非-总计)w.r.t。零成本抽象。
但是,通过使用 SingI
-style type class with a proxy (e.g. singByProxy
),我们不会遇到同样的问题:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
module Data.Test where
import GHC.Exts (Proxy#)
class SingIBool (b :: Bool) where
sing :: Proxy# b -> Bool
instance SingIBool 'False where
sing _ = False
instance SingIBool 'True where
sing _ = True
refurbulate :: SingIBool b => Proxy# b -> Int
refurbulate p
| sing p = 0
| otherwise = 1
特化 refurbulate @(Proxy# 'False)
不仅会实现为 const False
,也不会在值级别传递任何 Proxy#
参数,因此它更像是 coerce False :: Proxy# -> Bool
.整洁的!但是,我不会在现实世界中使用单例:(
回顾一下为什么单例失败(为了优化)并输入 classes 工作:
通过特化类型 class 实例,我们了解了 sing
的 RHS,从中我们可以推断出整体性。
通过专门化单例,我们可以知道参数的计算结果,如果计算终止。
知道类型 class 方法 x :: ()
的规范 RHS 比仅仅知道参数 x :: ()
只能计算一个非总值,惰性(例如 Haskell 的)设置。