为什么没有函数的Show实例?

  • 本文关键字:Show 实例 函数 haskell
  • 更新时间 :
  • 英文 :


只是一个快速的概念性问题,我目前正试图更好地学习和理解Haskell。

我知道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>

不是他们不能,而是通常没有一个好的理由。

但如果你愿意,你绝对可以:

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.

如果您想要show函数的文本表示,那么—您不能这样做。与Ruby、JS等元编程语言不同,Haskell代码对自己的内部结构知之甚少。

对于使用Data.Typeable的所有函数,有一个不完全的解决方案,而不仅仅是一个固定的字符串。

{-# LANGUAGE ScopedTypeVariables #-}
import Data.Typeable
instance (Typeable a, Typeable b) => Show (a->b) where
  show _ = show $ typeOf (undefined :: a -> b)
在ghci

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

不幸的是,如果没有类型签名,类型将变成默认值。

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

此解决方案适用于多个功能,因为a -> b -> ca -> (b -> c)相同,您可以将d = b -> c写成a -> d

> 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

这个方法不工作,然而,当它是未知的,如果函数的参数有可类型的类,然而,当map (+1)将工作map将不工作。

> map (+1)
[Integer] -> [Integer]
> map
<interactive>:233:1:
...

在浏览了Data.Data的内部结构和一两个实验之后,它似乎可以被重构得更一般化一些,覆盖更多的函数。

show是定义在Show类型类成员函数上的函数(如果你不知道类型类是什么,它有点像OOP接口)。

默认情况下,函数不是类型类的成员,因此不能打印它们。

可以用

使它成为类型类的成员
instance Show (a -> b) where
   show f = "Unicorns!!"

,但这里我们意识到为什么它不是默认实现的。没有一个简单、明显的函数表示,haskell不想猜测,因此没有实例。

唯一"允许的"实例将是实际打印出函数的实例,但这将需要实际的语言更改,即它将被硬连接到编译器中,这对于少数可能有用的情况来说是不值得的。

更进一步,这是一个重要的编译器变化,Haskell被编译了这意味着f = g

之间的区别
f =             g 

完全丢失了。但你肯定想在函数表示中看到它。因此,您必须在整个程序中拖着这个字符串。这绝对不是你想要的二进制文件。

如果你真的想让它打印独角兽!!不过,请随意。

最新更新