我尝试在Haskell中打印函数只是为了好玩,就像这个例子:
{-# LANGUAGE FlexibleInstances #-}
instance Show (Int -> Bool) where
show _ = "function: Int -> Bool"
Run Code Online (Sandbox Code Playgroud)
在GHCi中加载并运行和示例:
?> :l foo
[1 of 1] Compiling Main ( foo.hs, interpreted )
foo.hs:2:1: Warning: Unrecognised pragma
Ok, modules loaded: Main.
?> (==2) :: Int -> Bool
function: Int -> Bool
Run Code Online (Sandbox Code Playgroud)
但是,我希望看到每个函数都在调用时自行打印.
你不能将它作为一般函数,因为类型信息仅在编译时出现,但是Typeable如果类型是Typeable类的实例,则使用类来写足够接近的东西.
import Data.Typeable
instance (Typeable a, Typeable b) => Show (a -> b) where
show f = "Function: " ++ (show $ typeOf f)
Run Code Online (Sandbox Code Playgroud)
在ghci中测试这个
*Main> (+)
Function: Integer -> Integer -> Integer
*Main> (+10)
Function: Integer -> Integer
Run Code Online (Sandbox Code Playgroud)
但是,在将类型限制为具有Typeable实例的类型之前,这不适用于一般函数.
*Main> zip
<interactive>:3:1:
Ambiguous type variable `a0' in the constraint:
(Typeable a0) arising from a use of `print'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of an interactive GHCi command: print it
<interactive>:3:1:
Ambiguous type variable `b0' in the constraint:
(Typeable b0) arising from a use of `print'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of an interactive GHCi command: print it
*Main> zip :: [Int] -> [Bool] -> [(Int,Bool)]
Function: [Int] -> [Bool] -> [(Int,Bool)]
Run Code Online (Sandbox Code Playgroud)
我假设您希望该show方法打印函数的地址,这是Python的作用:
>>> def foo(a):
... return a
...
>>> print foo
<function foo at 0xb76f679c>
Run Code Online (Sandbox Code Playgroud)
实际上没有支持的方法(Haskell是一种安全的高级语言,从函数指针这样的低级细节中抽象出来),除非你愿意使用内部GHC函数unpackClosure#:
{-# LANGUAGE MagicHash,UnboxedTuples,FlexibleInstances #-}
module Main
where
import GHC.Base
import Text.Printf
instance Show (a -> a) where
show f = case unpackClosure# f of
(# a, _, _ #) -> let addr = (I# (addr2Int# a))
in printf "<function ??? at %x>" addr
main :: IO ()
main = print (\a -> a)
Run Code Online (Sandbox Code Playgroud)
测试:
$ ./Main
<function ??? at 804cf90>
Run Code Online (Sandbox Code Playgroud)
不幸的是,没有办法获取函数的名称,因为它只是在编译的可执行文件中不存在(可能有调试信息,但你不能指望它的存在).如果您的函数可以从C调用,您也可以使用C帮助程序获取其地址.