Haskell如何构造具有依赖类型的对象

时间:2016-01-05 10:59:22

标签: haskell dependent-type

我在数据'D'中使用了类型族来约束其中第一项的类型。 现在我需要从一些常用函数(如intermediate_func)创建“D B1”或“D B2”类型的对象。但是下面的代码不起作用。 有什么建议怎么做?或以另一种方式施加类似的约束。

data A1 = A1
data A2 = A2

data B1 = B1
data B2 = B2

data C a b where
  C1 :: Int →  C a b
  C2 :: Char →  C A1 b
  C3 :: Bool →  C A1 B1

type family ResT b where
  ResT B1 = C A1 B1
  ResT B2 = C A2 B2

data D b where
  D1 :: ResT B1 →  C A1 B1 →  D B1
  D2 :: ResT b →  C A1 b →  D b

-- This does not compile
intermediate_func :: Int →  D b
intermediate_func i = D2 (C1 i) (C1 i)

-- This works
-- intermediate_func :: Int -> D B2
-- intermediate_func i = D2 (C1 i) (C1 i)
-- So does this
-- intermediate_func :: Int -> D B1
-- intermediate_func i = D2 (C1 i) (C1 i)

2 个答案:

答案 0 :(得分:2)

您需要证明bB1B2,而不是其他任何内容。如上所述,可以调用intermediate_func :: Int → D String

您可以通过单身人士传递此类证据:

data S b where
   SB1 :: S B1
   SB2 :: S B2

intermediate_func :: S b → Int →  D b
intermediate_func SB1 i = D2 (C1 i) (C1 i)
intermediate_func SB2 i = D2 (C1 i) (C1 i)

如果要隐藏S b类型的单例参数,请查看this recent question。您可以使用类型类来实现。 E.g。

class CB b where getSB :: S b
instance CB B1 where getSB = SB1
instance CB B2 where getSB = SB2

intermediate_func :: SB b → Int → D b
intermediate_func SB1 i = D2 (C1 i) (C1 i)
intermediate_func SB2 i = D2 (C1 i) (C1 i)

intermediate_func_short :: CB b => Int → D b
intermediate_func_short = intermediate_func getSB

答案 1 :(得分:1)

使用类型类的解决方案:

{-# LANGUAGE GADTs #-}                                                                                             
{-# LANGUAGE TypeFamilies #-}                                                                                      
module Temp where                                                                                                  

data A1                                                                                                            
data A2                                                                                                            
data B1                                                                                                            
data B2                                                                                                            

data C a b where                                                                                                   
  C1 :: Int ->  C a b                                                                                              
  C2 :: Char ->  C A1 b                                                                                            
  C3 :: Bool ->  C A1 B1                                                                                           

class Intermediate b where                                                                                         
  type ResT b                                                                                                      
  intermediate_func :: Int ->  D b                                                                                 

data D b where                                                                                                     
  D1 :: ResT B1 ->  C A1 B1 ->  D B1                                                                               
  D2 :: ResT b ->  C A1 b ->  D b                                                                                  

instance Intermediate B1 where                                                                                     
  type ResT B1 = C A1 B1                                                                                           
  intermediate_func i = D2 (C1 i) (C1 i)                                                                           

instance Intermediate B2 where                                                                                     
  type ResT B2 = C A2 B2                                                                                           
  intermediate_func i = D2 (C1 i) (C1 i)