7

ちょっとした概念的な質問ですが、私は現在、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>
4

3 に答える 3

10

できないわけではありませんが、通常、正当な理由はありません。

ただし、必要に応じて、次のことができます。

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 のコードは自身の内部構造に関する知識がほとんどありません。

于 2013-04-05T00:01:00.267 に答える
8

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

このソリューションは、複数の関数アリティで機能します。これは、 whereと同様に記述できる whicha -> b -> cと同じであるためです。a -> (b -> c)a -> dd = 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

このメソッドは機能しませんが、関数のパラメーターが型付け可能なクラスを持っているかどうかが不明な場合は機能しませんが、その間map (+1)は機能しmapません。

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

<interactive>:233:1:
...

の内部Data.Dataと 1 つまたは 2 つの実験を一瞥した後、リファクタリングして、より一般化された、より多くの機能をカバーできるように思われます。

于 2013-04-06T01:32:25.423 に答える
3

show型クラスのメンバーである関数で定義される関数ですShow(型クラスが何であるかわからない場合は、OOP インターフェースのようなものです)。

デフォルトでは、関数は型クラスのメンバーではないため、出力できません。

型クラスのメンバーにすることができます

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

しかし、ここで、デフォルトで実装されていない理由がわかりました。関数の単純で明白な表現はなく、haskell は推測したくないため、インスタンスがありません。

唯一の「許容される」インスタンスは、実際に関数を出力するものですが、これには実際の言語の変更が必要になります。つまり、コンパイラに組み込まれます。 .

さらに、これは重要なコンパイラの変更です。Haskell はコンパイルされます。つまり、次のような違いがf = gあります。

f =             g 

その上で完全に失われます。しかし、関数表現でそれが必要になることは間違いありません。このため、プログラム全体でこの文字列を持ち歩く必要があります。これは、バイナリで必要なものではありません。

本当にユニコーンを印刷したいなら!! でも、ご自由にどうぞ。

于 2013-04-04T23:59:49.107 に答える