使用一些扩展程序,我可以这样做:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
type family TF (a :: Bool) where
TF 'True = Int
TF 'False = Double
data D a where
D :: TF a -> D a
请注意,构造函数D
可以以两种方式工作。之一:
D :: Int -> D 'True
或
D :: Double -> D 'False
使用这种模式,我可以根据它的类型完全改变构造函数的参数,同时重用它的名称。
但是,我也想要依赖它名称的参数数量。
我知道我可以用()
或Void
替换一些参数,但我宁愿完全删除它们。
有没有这样做?
答案 0 :(得分:1)
我不确定这是否正是@luqui在上面的评论中所考虑的,但您可以在类型类中创建一个智能构造函数,该类型调度其第一个参数的类型(或任何固定数字)初始参数)通过类型族确定剩余参数的数量和类型:
{-# LANGUAGE TypeFamilies #-}
data D = Int2 Int Int
| Double1 Double
deriving (Show)
class D1 a where
d :: a -> T2 a
type family T2 a where
T2 Int = Int -> D
T2 Double = D
instance D1 Int where
d x = \y -> Int2 x y -- or just `d = Int2`
instance D1 Double where
d x = Double1 x -- or just `d = Double1`
之后:
> d (2 :: Int) 3
Int2 2 3
> d (2 :: Double)
Double1 2.0
>
我不清楚如何将此概括为需要条件派遣的情况:
data D = IntStringDouble Int String Double
| Int2 Int Int
| Double1 Double
deriving (Show)
因为您需要以下内容:
T2 Int = a -> T3 a
T3
另一个类型系列用于发送的下一步,我不认为有任何方式可以使类型系列的RHS具有多态性。也许其他人可以看到一种方式。
无论如何,它可能比它的价值更麻烦。