Haskell Labeled AST:没有实例(Show1(Label a)),如何构造实例?

时间:2017-09-08 13:20:34

标签: haskell abstract-syntax-tree recursive-datastructures deriving

我想要一个带注释的AST,所以我定义了那些递归数据结构 使用Fix

data Term a 
  = Abstraction Name a
  | Application a a
  | Variable Name
  deriving (Read,Show,Eq,Functor,Foldable,Traversable)

data Label a b 
  = Label a (Term b)
  deriving (Read,Show,Eq,Functor,Foldable,Traversable)

newtype Labeled a 
  = Labeled (Fix (Label a))
  deriving (Show)

我希望能show Labeled a,但编译器不满意:

No instance for (Show1 (Label a))  
arising from the first field of `Labeled' (type `Fix (Label a)')

什么是课程Show1,如何定义适当的实例才能展示Labeled a

1 个答案:

答案 0 :(得分:2)

Show1是你可以称之为“高阶showables”的类:类型构造函数,只要它们的参数可以显示就可以显示。出于快速和宽松推理的目的,您可以将Show1视为大致相同的声明(另请参阅showsPrec1):

class Show1 f where
    show1 :: Show a => f a -> String

这是考虑Show1的另一种不准确但有用的方法。我正在使用the constraints library"entailment" operator声明只要f aShow就应该是a的实例。这个模型有点简单,但可能不太实用。

class Show1 f where
    show1 :: Show a :- Show (f a)

无论如何,如果Fix :: (* -> *) -> *的参数是高阶可显示的,则instance Show1 f => Show (Fix f) where showsPrec d (Fix a) = showParen (d >= 11) $ showString "Fix " . showsPrec1 11 a 是可显示的。来自the source code

recursion-schemes

StandaloneDeriving的作者可以使用Show撰写他们的deriving instance Show (f (Fix f)) => Show (Fix f) 个实例...

UndecidableInstances

...但此上下文需要Show1

为给定仿函数编写{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-} {-# LANGUAGE TemplateHaskell #-} import Text.Show.Deriving import Data.Functor.Foldable type Name = String data Term a = Abstraction Name a | Application a a | Variable Name deriving (Read, Show, Eq, Functor, Foldable, Traversable) deriveShow1 ''Term data Label a b = Label a (Term b) deriving (Read, Show, Eq, Functor, Foldable, Traversable) deriveShow1 ''Label newtype Labeled a = Labeled (Fix (Label a)) deriving (Show) 实例的最简单方法是使用the deriving-compat libraryTemplate Haskell helper

instance Show1 Term
instance Show a => Show1 (Label a)

这将生成以下实例,

Labeled

准确地为您提供instance Show a => Show (Labeled a) 派生实例的所需内容:

DECLARE @tbl TABLE (dat NVARCHAR(64))
INSERT INTO @tbl (dat) VALUES ('2017-06-30 09:40:05.130')
INSERT INTO @tbl (dat) VALUES ('26/4/2016 00:00:00')
INSERT INTO @tbl (dat) VALUES ('2017-08-21 12:52:23.063000000')
INSERT INTO @tbl (dat) VALUES ('5/4/2016 00:00:00')
DECLARE @cdat NVARCHAR(64)

DECLARE c CURSOR LOCAL FAST_FORWARD READ_ONLY FOR 
    SELECT dat FROM @tbl
OPEN c
FETCH NEXT FROM c INTO @cdat
WHILE @@fetch_status = 0 BEGIN 

    BEGIN TRY  
        /*convert and do the job*/
        SELECT CONVERT(DATETIME2,@cdat)--into normal table
    END TRY  
    BEGIN CATCH  
        /*handle failed conversions*/
        SELECT @cdat --into failstable?
        PRINT 'failed conversion, data:' + @cdat
    END CATCH  

    FETCH NEXT FROM c INTO @cdat
END 
CLOSE c
DEALLOCATE c

(PS。您是否考虑过使用像bound这样的库来管理您的学期语言中的姓名和活页夹?)