简体   繁体   中英

How print functions in Haskell like a python or scala?

I try to print functions in Haskell only for fun, like this example:

{-# LANGUAGE FlexibleInstances #-}

instance Show (Int -> Bool) where
    show _ = "function: Int -> Bool"

loading in GHCi and run and example:

λ> :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

But, I wish to see that every function print yourself at invocation.

You can not have this for a general function as type information is present only at compile time, but you use Typeable class for writing something close enough if the type is an instance for Typeable class.

import Data.Typeable

instance (Typeable a, Typeable b) => Show (a -> b) where
    show f = "Function: " ++ (show $ typeOf f)

Testing this in ghci

*Main> (+)
Function: Integer -> Integer -> Integer
*Main> (+10)
Function: Integer -> Integer

But this will not work for general functions until the type is restricted to a type that has Typeable instance.

*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)]

I'm assuming that you want the show method to print the function's address , which is what Python does:

>>> def foo(a):
...     return a
... 
>>> print foo
<function foo at 0xb76f679c>

There is really no supported way to do it (Haskell is a safe, high-level language that abstracts from such low-level details as function pointers), unless you're willing to use the internal GHC function 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)

Testing:

$ ./Main 
<function ??? at 804cf90>

Unfortunately, there is no way to get the function's name, since it is simply not present in the compiled executable (there may be debug information, but you can't count on its presence). If your function is callable from C, you can also get its address by using a C helper.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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