繁体   English   中英

在运行时使用GADT玩杂耍

[英]Type juggling with GADTs at runtime

我正在设计一种类型化的形式语言,即每个字母都有特定类型表示形式的形式语言。 到目前为止,我有以下内容:

{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE InstanceSigs          #-}
{-# LANGUAGE RankNTypes            #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TypeInType            #-}
{-# LANGUAGE TypeFamilies          #-}

import Data.Kind

data Typey (s :: c) = Marker

class Character c where
  showVal :: Typey (s :: c a) -> a -> ShowS

class Character (Letter l) => Alphabet l where
  data family Letter l :: * -> *

data Symbol l (a :: Letter l s) where
  Terminal :: (Alphabet l) => s -> Symbol l (a :: Letter l s)

instance (Alphabet l) => Show (Symbol l a) where
  showsPrec d (Terminal val) = showVal (Marker :: Typey a) val

-- Example language
data ExampleLanguage = ExampleLanguage

instance Alphabet ExampleLanguage where
  data Letter ExampleLanguage a where
    Variable :: Letter ExampleLanguage String
    Comment :: Letter ExampleLanguage String
    EqualSign :: Letter ExampleLanguage ()
    Deref :: Letter ExampleLanguage ()

instance Character (Letter ExampleLanguage) where
--    showVal (_ :: Typey Variable) = showString
--    showVal (_ :: Typey Comment) = showString
--    showVal (_ :: Typey EqualSign) = const $ showString "="
--    showVal (_ :: Typey Deref) = const $ showString "*"
    showVal _ = const $ showString "error"
test :: Symbol ExampleLanguage Comment
test = Terminal "some comment"

您可能已经看到我开始实现showVal但是在这里,我在完成实现方面遇到了问题。 当我尝试取消注释instance Letter (Character ExampleLanguage)instance Letter (Character ExampleLanguage) ,编译器会很快抱怨:

main.hs:40:14: error:
    • Couldn't match type ‘a1’ with ‘()’
      ‘a1’ is a rigid type variable bound by
        the type signature for:
          showVal :: forall k (a :: k) a1 (s :: Character
                                                  ExampleLanguage a1).
                     Typey s -> a1 -> ShowS
        at main.hs:38:5
      Expected type: Typey 'EqualSign
        Actual type: Typey s
    • When checking that the pattern signature: Typey 'EqualSign
        fits the type of its context: Typey s
      In the pattern: _ :: Typey EqualSign
      In an equation for ‘showVal’:
          showVal (_ :: Typey EqualSign) = const $ showString "="
    • Relevant bindings include
        showVal :: Typey s -> a1 -> ShowS (bound at main.hs:38:5)

我不确定我是否理解编译器在抱怨什么。 从GADT对Character ExampleLanguage ExampleLanguage的定义可以很明显地看出,我正在尝试对不同的构造函数进行模式匹配,并根据Letter输出不同的String。

我该如何进行这项工作? 数据格式不是固定的,只要Symbol包含有关字母,字母和字母表示类型的类型信息,就可以对其进行一些修改。

GADT构造函数上的模式匹配,而不是其类型上的匹配

{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE TypeFamilies          #-}

class Character c where
  showVal :: c a -> a -> ShowS

class Character (Letter l) => Alphabet l where
  data family Letter l :: * -> *

-- Example language
data ExampleLanguage = ExampleLanguage

instance Alphabet ExampleLanguage where
  data Letter ExampleLanguage a where
    Variable :: Letter ExampleLanguage String
    Comment :: Letter ExampleLanguage String
    EqualSign :: Letter ExampleLanguage ()
    Deref :: Letter ExampleLanguage ()

instance Character (Letter ExampleLanguage) where
    showVal Variable = showString
    showVal Comment = showString
    showVal EqualSign = const $ showString "="
    showVal Deref = const $ showString "*"

将此Symbol包含在Symbol以便以后可以对其进行模式匹配。

{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE TypeInType            #-}

data Symbol l (a :: Letter l s) where
  Terminal :: Letter l s -> s -> Symbol l (a :: Letter l s)

instance (Alphabet l) => Show (Symbol l a) where
  showsPrec d (Terminal tag val) = showVal tag val

test :: Symbol ExampleLanguage Comment
test = Terminal Comment "some comment"

暂无
暂无

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

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