单例参数的特化

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 的)设置。