3

次の例のように、楽しみのためだけに Haskell で関数を印刷しようとしています。

{-# LANGUAGE FlexibleInstances #-}

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

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

しかし、すべての関数が呼び出し時に自分自身を出力することを望みます。

4

2 に答える 2

9

型情報はコンパイル時にのみ存在するため、これを一般的な関数に使用することはできませんがTypeable、型がクラスのインスタンスである場合は、十分に近いものを記述するためにクラスを使用しますTypeable

import Data.Typeable

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

これをghciでテストする

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

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)]
于 2012-10-14T07:19:46.520 に答える
7

showメソッドで関数のaddressを出力する必要があると仮定しています。これは Python が行うことです。

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

内部GHC関数を使用するつもりがない限り、それを行う方法は実際にはサポートされていません(Haskellは、関数ポインターなどの低レベルの詳細から抽象化する安全な高レベル言語です) 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)

テスト:

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

残念ながら、コンパイルされた実行可能ファイルには存在しないため、関数の名前を取得する方法はありません (デバッグ情報はあるかもしれませんが、その存在を当てにすることはできません)。関数が C から呼び出せる場合は、C ヘルパーを使用してそのアドレスを取得することもできます。

于 2012-10-14T05:49:41.237 に答える