如何在Haskell中为b-> a创建一个Show实例?

Eya*_*yal 2 haskell

我正在尝试构造一个本质上是二叉树的数据类型,其中:每个节点的左分支是一个函数,可以作用于每个节点的右分支中的变量.我是Haskell的新手,我不确定我是否会以正确的方式解决这个问题,但我目前的问题是我无法弄清楚如何将我的类型添加到Show类型类中.这是我的尝试:

{-# LANGUAGE ExistentialQuantification #-}
-- file: TS.hs                                                                                                                                                       

data TypeSentence a = forall b. Apply (TypeSentence (b->a)) (TypeSentence b)
                    | Expr a

instance (Show a) => (Show (TypeSentence a)) where
        show (Expr x) = show x
        show (Apply x y) = (show x) ++ " " ++ (show y)

instance (Show (TypeSentence b->a)) where
    show (Expr x) = show "hello"

x = Expr 1
f = Expr (+1)
s = Apply f x
Run Code Online (Sandbox Code Playgroud)

但是,当我将其加载到ghci时,我收到以下错误:

TS.hs:9:24:                                                                                                                                                          
     Could not deduce (Show (b -> a)) from the context ()                                                                                                             
     arising from a use of `show' at TS.hs:9:24-29                                                                                                                  
      Possible fix:                                                                                                                                                    
      add (Show (b -> a)) to the context of the constructor `Apply'                                                                                                  
      or add an instance declaration for (Show (b -> a))                                                                                                             
        In the first argument of `(++)', namely `(show x)'                                                                                                               
        In the expression: (show x) ++ " " ++ (show y)                                                                                                                   
        In the definition of `show':                                                                                                                                     
           show (Apply x y) = (show x) ++ " " ++ (show y)                                                                                                               
 Failed, modules loaded: none. 
Run Code Online (Sandbox Code Playgroud)

我是如何添加Show(b-> a)声明的?

谢谢.

Ant*_*sky 7

您编写的代码存在一些问题,因此我将逐一介绍它们.

  1. 您无法为其添加特别丰富的实例Show (a -> b).考虑一下如何写它:

    instance Show (a -> b) where
      show f = error "What goes here?"
    
    Run Code Online (Sandbox Code Playgroud)

    既然f是一个函数,除了将它应用于一个值之外,你无法用它做任何事情; 并且由于a是完全多态的类型,因此无法创建a要应用的类型值f.所以你唯一的选择是这样的

    instance Show (a -> b) where
      show _ = "<function>"
    
    Run Code Online (Sandbox Code Playgroud)

    正如Daniel Fischer在评论中所说,这可以在Text.Show.Functions模块中找到.不过,我真的不打扰这个; 我只想写点什么

    instance Show a => Show (TypeSentence a) where
      show (Apply _ x) = "Apply _ " ++ show x -- This still won't work; see below
      show (Expr x)    = "Expr " ++ show x
    
    Run Code Online (Sandbox Code Playgroud)

    既然show只能为任何函数返回一个字符串,只需直接内联即可.

  2. 尽管如此,你仍然无法编写那个Show实例.如果您尝试编译上面的实例,则会收到以下错误:

    TS.hs:8:36:
        Could not deduce (Show b) arising from a use of `show'
        from the context (Show a)
          bound by the instance declaration
          at TS.hs:7:10-40
        Possible fix:
          add (Show b) to the context of
            the data constructor `Apply'
            or the instance declaration
        In the second argument of `(++)', namely `show x'
        In the expression: "Apply _ " ++ show x
        In an equation for `show': show (Apply _ x) = "Apply _ " ++ show x
    
    Run Code Online (Sandbox Code Playgroud)

    问题是,在你的定义中TypeSentence,Apply隐藏了一个由任意存在隐藏类型参数化的变量(x在定义中绑定show).但是不能保证可以显示,所以不会进行类型检查,这是上面产生的错误:没有实例,因为它是任意的.因此,要摆脱这种情况,最简单的方法就是TypeSentencebbshow xShow bb

    instance Show a => Show (TypeSentence a) where
      show (Apply _ _) = "Apply _ _"
      show (Expr x)    = "Expr " ++ show x
    
    Run Code Online (Sandbox Code Playgroud)

    这并不是特别有用.所以也许没有一个好的Show实例TypeSentence.(这没关系.许多有用的类型都没有Show实例.)

  3. 这个与其他一切无关.该instance Show (TypeSentence b -> a)声明试图宣布的一个实例Show为从函数TypeSentence ba; 如果你重新表达为instance Show (TypeSentence (b -> a)),你仍然需要FlexibleInstancesOverlappingInstances扩展来获得编译.所以你应该只是斧头.