12

Ruby のような純粋なオブジェクト指向言語について考えていました。Ruby では、数値、int、浮動小数点数、文字列など、すべてがそれ自体がオブジェクトです。これは純粋な関数型言語でも同じことですか? たとえば、Haskell では Numbers と Strings も機能しますか?

Haskell は、データや操作を含むすべてを関数として表すラムダ計算に基づいていることを知っています。「純粋な関数型言語」がすべてを関数としてモデル化し、関数がほとんどの場合同じ入力で同じ出力を返し、状態を持たないという定義を維持することは、私には論理的に思えます。

4

5 に答える 5

15

理論的に考えればいいんだけど…

Ruby と同じように、すべてがオブジェクトではありません(たとえば、引数リストは object ではありません)。Haskell のすべてが関数ではありません。

詳細については、このきちんとした投稿をご覧ください: http://conal.net/blog/posts/everything-is-a-function-in-haskell

于 2012-11-27T22:58:59.257 に答える
14

@wrhallは良い答えを出します。ただし、純粋なラムダ計算では、すべてが関数であることが一貫しており、言語はチューリング完全です(Haskellなどの純粋な計算を表現できます)。

それはあなたにいくつかの非常に奇妙なことを与えます、なぜならあなたが何かにできる唯一のことはそれを他のものに適用することだからです。いつ何かを観察するようになりますか?あなたはいくつかの価値fを持っていて、それについて何かを知りたいのですが、あなたの唯一の選択はそれxをgetに適用することですf x。これは別の関数であり、唯一の選択はそれを別の値に適用することyですf x y

多くの場合、私は純粋なラムダ計算を、関数ではなく、関数自体を表現することしかできないものの変換について話していると解釈します。つまり、関数を作成できます(再帰とletのためのHaskelly構文シュガーを少し使用して):

purePlus = \zero succ natCase -> 
   let plus = \m n -> natCase m n (\m' -> plus m' n)
   in plus (succ (succ zero)) (succ (succ zero))

2+2ここでは、非関数などがあることを知らなくても、計算を表現しました。定義している関数の引数として必要なものを単純に取りました。これらの引数の値は、チャーチ数にすることも、「実数」(それが意味するものは何でも)にすることもできます。私の定義は関係ありません。

そして、あなたはHaskellの同じことを考えることができます。機能ではないものがあると考える特別な理由はなく、すべてが機能であると考える特別な理由もありません。しかし、Haskellの型システムは、少なくとも、数値に引数を適用することを防ぎます(fromInteger今考えている人は誰でも、自分の舌を保持する必要があります!:-)。上記の解釈では、数値は必ずしも関数としてモデル化されているとは限らないため、必ずしも引数を適用できるとは限りません。

今のところはっきりしない場合、この答え全体は技術的/哲学的な余談であり、あなたの質問に対する簡単な答えは「いいえ、すべてが関数型言語の関数であるとは限りません」です。関数は、引数を適用できるものです。それだけです。

于 2012-11-27T23:13:30.473 に答える
6

この質問に対する非常に異なる角度:Haskellのあらゆる種類のデータは、チャーチエンコーディングと呼ばれる手法を使用して関数として表すことができます。これは制御の反転の一形態です。データを消費する関数にデータを渡す代わりに、一連のクロージャ内にデータを非表示にし、データを消費するために、このデータの処理方法を説明するコールバックを渡します。

たとえば、リストを使用するプログラムは、リストの代わりに関数を使用するプログラムに変換できます。

-- | A list corresponds to a function of this type:
type ChurchList a r = (a -> r -> r)  --^ how to handle a cons cell
                   -> r              --^ how to handle the empty list
                   -> r              --^ result of processing the list

listToCPS :: [a] -> ChurchList a r
listToCPS xs = \f z -> foldr f z xs

その関数は、その出発点として具体的なリストを取りますが、それは必須ではありません。ChurchList純粋関数から関数を構築できます。

-- | The empty 'ChurchList'.
nil :: ChurchList a r
nil = \f z -> z

-- | Add an element at the front of a 'ChurchList'.
cons :: a -> ChurchList a r -> ChurchList a r
cons x xs = \f z -> f z (xs f z)

foldChurchList :: (a -> r -> r) -> r -> ChurchList a r -> r
foldChurchList f z xs = xs f z

mapChurchList :: (a -> b) -> ChurchList a r -> ChurchList b r
mapChurchList f = foldChurchList step nil
    where step x = cons (f x)

filterChurchList :: (a -> Bool) -> ChurchList a r -> ChurchList a r
filterChurchList pred = foldChurchList step nil
    where step x xs = if pred x then cons x xs else xs

最後の関数はを使用しますBoolが、もちろん関数に置き換えることもできBoolます。

-- | A Bool can be represented as a function that chooses between two 
-- given alternatives.
type ChurchBool r = r -> r -> r

true, false :: ChurchBool r
true a _ = a
false _ b = b

filterChurchList' :: (a -> ChurchBool r) -> ChurchList a r -> ChurchList a r
filterChurchList' pred = foldChurchList step nil
    where step x xs = pred x (cons x xs) xs

この種の変換は基本的にすべての型に対して実行できるため、理論的には、Haskellのすべての「値」型を取り除き、型、型構築子、および()(->)IOおよびreturn適切なプリミティブのセット>>=のみを保持できます。これは明らかに非現実的であり、パフォーマンスが低下します(好みに合わせて書いてみてください)。IOIOtailChurchList :: ChurchList a r -> ChurchList a r

于 2012-11-28T01:24:15.283 に答える
6

「純粋な機能」の「純粋」とは、「副作用のない」種類の純粋さを指します。人々が「純粋なオブジェクト指向言語」について話すときに使用される「純粋な」の意味とはほとんど関係がありません。これは単に、言語が純粋に (のみ) オブジェクトで操作することを意味します。

Java や C++ などの言語には、オブジェクトとあまり共通点のない値を明確に持っている言語があるため、オブジェクト指向言語を分類するために使用するのに、pure-as-in-only が妥当な区別であるからです。また、Python や Ruby などの言語もあり、すべての値がオブジェクトであると主張できます1 。

関数型言語の場合、言語が操作できるすべての値が関数であるという意味で「純粋関数型」である実用的な言語はありませんそのような言語でプログラミングすることは確かに可能です。ラムダ計算の最も基本的なバージョンには、関数ではないものの概念はありませんが、計算したいものを関数として表現する方法を考え出すことで、任意の計算を行うことができます。2

しかし、ラムダ計算の単純さとミニマリズムは、プログラミングに関することを証明するのに優れている傾向がありますが、実際には、そのような「生の」プログラミング言語で実質的なプログラムを書くのは厄介です。数値などの基本的なものの関数表現も、実際の物理マシンに実装するには非常に非効率になる傾向があります。

しかし、関数型のスタイルを奨励するがどこでも追跡されない副作用を許容する言語と、実際に関数が「純粋な」関数 (数学関数と同様) であることを強制する言語との間には、非常に重要な違いがあります。オブジェクト指向プログラミングは、不純な計算の使用に非常に強く結びついている3ため、この意味で純粋な実用的なオブジェクト指向プログラミング言語はありません。

したがって、「純粋な関数型言語」の「純粋」は、「純粋なオブジェクト指向言語」の「純粋」とは非常に異なるものを意味します。4いずれの場合も、「純粋対非純粋」の区別は、他の種類の言語に適用されるとはまったく興味のないものであるため、この用語の使用を標準化する強い動機はありません。


1私が知っているすべての「純粋なオブジェクト指向」言語には、選択すべき例外的なケースがありますが、それはあまり興味深いものではありません。あるクラスのインスタンスである言語では、オブジェクトの比喩がはるかに進んでいることは明らかであり、そのクラスは、オブジェクト以外のもの1である言語よりもサブクラス化できます。1

2 とにかく、すべての計算は表現に関するものです。コンピュータは、数字やその他のことについて何も知りません。それらは、数値を表すために使用するビットパターンと、数値の操作に対応するビットパターンの操作を持っているだけです (そのように設計されているため)。

3これも基本的なことではありません。この意味で純粋な「純粋な」オブジェクト指向言語を設計できます。とにかく、OOコードのほとんどを純粋に書く傾向があります。

4これがわかりにくいと思われる場合は、「機能」、「オブジェクト」、および「言語」という用語が、他のコンテキストでも大きく異なる意味を持っていることを考えるかもしれません。

于 2012-11-28T03:18:17.293 に答える
0

getChar :: IO Char関数かどうか?Haskell Report には定義がありません。しかし、それはgetChar 関数であると述べています(こちらを参照)。(まあ、少なくともそれは関数であると言えます。)

だから答えはYESだと思います。

「すべてが関数である」以外に「関数」の正しい定義はないと思います。(「正しい定義」とは何ですか? 良い質問です...) 次の例を考えてみましょう:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Applicative

f :: Applicative f => f Int
f = pure 1

g1 :: Maybe Int
g1 = f

g2 :: Int -> Int
g2 = f

f関数またはデータ型ですか? 場合によります。

于 2012-11-28T10:30:09.580 に答える