简体   繁体   English

为什么没有Show函数实例?

[英]Why is there no Show instance for functions?

Just a quick conceptual question, I am currently trying to learn and understand Haskell better. 只是一个快速的概念性问题,我目前正在尝试更好地学习和理解Haskell。

I know the Show function is used to convert values to strings, but why can't function types be used with show? 我知道Show函数用于将值转换为字符串,但是为什么不能在show中使用函数类型?

Prelude> (\x -> x*3)

<interactive>:7:1:
    No instance for (Show (a0 -> a0))
      arising from a use of `print'
    Possible fix: add an instance declaration for (Show (a0 -> a0))
    In a stmt of an interactive GHCi command: print it
Prelude>

It's not that they can't, but that there's not usually a good reason to. 不是因为他们做不到,而是通常没有充分的理由。

But if you'd like, you definitely can: 但是,如果您愿意,您绝对可以:

Prelude> :{
Prelude| instance Show (a -> b) where
Prelude|    show _ = "A function."
Prelude| :}
Prelude> print (\x -> x + 7)
A function.
Prelude> print (\a b c -> a + b + c)
A function.

If you'd like to show the textual representation of the function, well - you can't do that. 如果您想show该函数的文本表示形式,那么-您不能这样做。 Unlike metaprogramming languages like Ruby, JS, etc, Haskell code very little knowledge of its own internals. 与元编程语言(如Ruby,JS等)不同,Haskell对自身内部结构的了解很少。

There is a partial solution that goes beyond just a fixed string for all functions using Data.Typeable. 对于使用Data.Typeable的所有函数,有一部分解决方案不只是固定字符串。

{-# LANGUAGE ScopedTypeVariables #-}

import Data.Typeable

instance (Typeable a, Typeable b) => Show (a->b) where
  show _ = show $ typeOf (undefined :: a -> b)

in ghci 在ghci

> let test :: Int->Int; test x = x + x
> test
Int -> Int

Unfortunately without a type signature the type will go to it default. 不幸的是,如果没有类型签名,该类型将默认使用它。

> let test x = x + x
> test
Integer -> Integer

This solution works on multiple function arities because a -> b -> c is the same as a -> (b -> c) which you might as well write as a -> d where d = b -> c . 此解决方案适用于多种功能变量,因为a- a -> b -> ca -> (b -> c) ,您也可以将其写为a- a -> d ,其中d = b -> c

> let m10 a b c d e f g h i j = a * b * c * d * e * f * g * h* i * j
> m10
Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer
        -> Integer -> Integer -> Integer -> Integer

This method does not work however when it is unknown if parameters of the function have the typeable class however so while map (+1) will work map will not. 但是,如果未知函数的参数是否具有可键入的类,则此方法将不起作用,因此map (+1)起作用时map不会起作用。

> map (+1)
[Integer] -> [Integer]
> map

<interactive>:233:1:
...

After glancing at the internals of Data.Data and an experiment or two it seems like it could be refactored to be a little more generalized cover more functions. 看完Data.Data的内部Data.Data和一个或两个实验之后,似乎可以将其重构为更具通用性的功能。

show is the function that is defined on functions that are members of the Show typeclass (if you don't know what a typeclass is, it's kinda like an OOP interface). show是在Show类型类的成员的函数上定义的函数(如果您不知道类型类是什么,则有点像OOP接口)。

By default, functions are not members of the typeclass, so we can't print them. 默认情况下,函数不是typeclass的成员,因此我们无法打印它们。

We could make it a member of the typeclass with 我们可以使它成为typeclass的成员

instance Show (a -> b) where
   show f = "Unicorns!!"

but here we realize why it isn't implemented by default. 但是在这里我们知道为什么默认情况下不实现它。 There isn't a simple, obvious representation of functions and haskell doesn't want to guess, and thus no instance. 没有简单,明显的函数表示,并且haskell不想猜测,因此没有实例。

The only "permissible" instance would be one that actually prints out the function, but this would require actual language change, ie it would be hardwired into the compiler, which just isn't worth it for the few cases in which it could be useful. 唯一的“允许”实例将是实际打印出该函数的实例,但这将需要实际的语言更改,即将其硬连线到编译器中,这在少数情况下不值得使用,这是不值得的。

Further more it's a nontrivial compiler change, Haskell is compiled which means the differences between something like f = g and 更重要的是,这是不平凡的编译器更改,Haskell已编译,这意味着f = g

f =             g 

are entirely lost on it. 完全迷失了它。 But you'd definitely want that in your function representation. 但是,您绝对希望在函数表示中使用它。 Because of this, you'd have to lug around this string through out the program. 因此,您必须在整个程序中使用该字符串。 This is definitely not what you want in a binary. 绝对不是您想要的二进制文件。

If you really want it to print unicorns!! 如果您真的想要它打印独角兽! though, feel free. 不过,请放心。

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

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