繁体   English   中英

用GHC类型级别的文字替换自建的自然

[英]Replacing self built Naturals with GHC type level literals

我写了一些代码,它采用异构列表并对其进行索引。

{-# Language GADTs, FunctionalDependencies, MultiParamTypeClasses, KindSignatures, DataKinds, TypeOperators, FlexibleInstances, UndecidableInstances #-}

import Data.Kind

data Nat = Z | S Nat

data Natural a where
  Zero :: Natural 'Z
  Succ :: Natural a -> Natural ('S a)

data HList a where
  EmptyList :: HList '[]
  Cons :: a -> HList b -> HList (a ': b)

class IndexType (n :: Nat) (a :: [Type]) (b :: Type) | n a -> b where
  index :: (Natural n) -> (HList a) -> b

instance IndexType 'Z (a ': b) a where
  index _ (Cons a _) = a

instance IndexType a b c => IndexType ('S a) (d ': b) c where
  index (Succ a) (Cons _ b) = index a b

为此,我实现了自己的NatNatural类型。 Nat存在仅仅是为了提升到种类水平而Natural存在以实现Nat -> Type

现在,我宁愿用GHC.TypeLitsNat样的,而不是我自己的。然而,当我尝试了我开始打墙的理解方面翻译我的代码。

我想构建我的IndexType类,声明行不会改变任何类

class IndexType (n :: Nat) (a :: [Type]) (b :: Type) | n a -> b where

由于GHC.TypeLits也有自己的Nat类。 但是GHC.TypeLits没有我所看到的Natural的替代品,即我缺少Nat -> Type 现在我可以建立一个等价物

data Natural a = Natural

但这基本上等同于Proxy类型,所以我可以使用它。

{-# Language GADTs, FunctionalDependencies, MultiParamTypeClasses, KindSignatures, DataKinds, TypeOperators, FlexibleInstances, UndecidableInstances #-}

import Data.Kind
import GHC.TypeLits
import Data.Proxy

data HList a where
  EmptyList :: HList '[]
  Cons :: a -> HList b -> HList (a ': b)

class IndexType (n :: Nat) (a :: [Type]) (b :: Type) | n a -> b where
  index :: (Proxy n) -> (HList a) -> b

现在, IndexType类的第一个实例很简单:

instance IndexType 0 (a ': b) a where
  index _ (Cons a _) = a

然而,第二个开始困惑我。 第一行似乎就好了

instance IndexType a b c => IndexType (1 + a) (d ': b) c where

但是在第二行我不知道如何在原始代码中替换Succ Proxy的数据构造函数是Proxy所以我想它必须使用那个构造函数,所以我必须写一些像:

  index Proxy (Cons _ b) = index a b

但现在我拉的定义, a凭空的。 我认为它必须是另一个Proxy因为索引采用Proxy ,但我不知道如何强制它是正确的类型。

这个怎么样?

class IndexType (n :: Nat) (a :: [Type]) (c :: Type) | n a -> c where           
  index ::  (Proxy n) -> (HList a) -> c                                         
instance IndexType 0  (a ': b) a where                                          
  index _ (Cons a _) = a                                                        
instance {-# OVERLAPS #-} (IndexType (a-1) b c) => IndexType a (d ': b) c where 
  index _ (Cons _ b) = index (Proxy @(a-1)) b                                   

这将使用一些额外的扩展,包括ScopedTypeVariablesTypeApplications PoC(在GHC 8.2.2上测试):

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Foo where
import Data.Kind
import GHC.TypeLits
import Data.Proxy

data HList a where
  EmptyList :: HList '[]
  Cons :: a -> HList b -> HList (a ': b)

class IndexType (n :: Nat) (a :: [Type]) (c :: Type) | n a -> c where
  index ::  (Proxy n) -> (HList a) -> c
instance IndexType 0  (a ': b) a where
  index _ (Cons a _) = a
instance {-# OVERLAPS #-} (IndexType (a-1) b c) => IndexType a (d ': b) c where
  index _ (Cons _ b) = index (Proxy @(a-1)) b

list :: HList '[Int, Bool]
list = Cons (5 :: Int) (Cons True EmptyList)
int :: Int
int = index (Proxy @0) list
bool :: Bool
bool = index (Proxy @1) list

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM