2016-10-27 19 views
6

私はこのコードをfold ((,) <$> sum <*> product)というタイプのシグネチャ:: (Foldable t, Num a) => t a -> (a, a)で見つけました。完全に失われました。ハスケル:実際にタイプfはどういう意味ですか?

私はそれが何をしているのか知っていますが、私はどのようにわかりません。だから私はghciの小さな部分に分割しようとしました:

すべては大丈夫、基本的なものです。

λ: :t (,) <$> sum 
(,) <$> sum :: (Foldable t, Num a) => t a -> b -> (a, b) 

そして私は再び失われています...

私はf at a -> aを回すが、どのようにそれが行われていることは私には謎ですいくつかの魔法の出来事があることがわかります。 (sumFunctorのも、インスタンスではありません!)

私はいつもf aaが含まれていますが、意味は非常に深いように見える箱fのいくつかの種類であると考えています。あなたの例では

+1

' <$>中置されています。 – chepner

答えて

5

ファンクタfは次のように定義されている、いわゆる「リーダーファンクタ」、次のとおりです。もちろん

newtype Reader r = Reader (r -> a) 

、Haskellで、これが機能するためにネイティブに実装するので、ノーがあるさ実行時にラップまたはアンラップする。

対応FunctorApplicativeインスタンスは、このようになりますように

instance Functor f where 
    fmap :: (a -> b) -> (r -> a)_-> (r -> b) 
    fmap f g = \x -> f (g x) -- or: fmap = (.) 

instance Applicative f where 
    pure :: a -> (r -> a) -- or: a -> r -> a 
    pure x = \y -> x -- or: pure = const 
    (<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b) 
    frab <*> fra = \r -> frab r (fra r) 

、リーダファンクタ型を生成コンテキストrを有し、他の全てのファンクタのような、あまりにも「ボックス」であるa

それでは(,) <$> sumを見てみましょう:

:t (,) :: a -> b -> (a, b) 
:t fmap :: (d -> e) -> (c -> d) -> (c -> e) 
:t sum :: Foldable t, Num f => t f -> f 

現在t fb -> (a, b)ca ~ fedタイプを特化することができます。今、私たちが得る:

:t (<$>) -- spcialized for your case 
:: Foldable t, Num f => (a -> (b -> (a, b))) -> (t f -> f) -> (t f -> (b -> (a, b))) 
:: Foldable t, Num f => (f -> b -> (f, b)) -> (t f -> f) -> (t f -> b -> (f, b)) 

は、関数を適用する:

GHCが言うまさにある
:t (,) <$> sum 
:: Foldable t, Num f => (t f -> b -> (f, b)) 

+1

Nitpick:この場合、「背後で」ラッピングやアンラッピングはありません。あなたが言及したインスタンスは、裸の関数のために利用できるので、 'Reader'ラッパー(これは主に余分な明快さと可読性を提供するために存在します)はここでは関与しません。 – duplode

+0

@duplodeええ、私はそれが不明だと思う。私はそれを追加します、ありがとう。 – ThreeFx

2

短い答えはf ~ (->) (t a)です。理由を調べるには、sumのタイプシグネチャをわずかに並べ替えてください。->を中置演算子の代わりに接頭演算子として使用してください。一般に

​​

(->) rは、任意の引数型rためのファンクタです。

fmap :: (a -> b) -> f a -> f b 
    :: (a -> b) -> ((->) r) a -> ((->) r) b 
    :: (a -> b) -> (r -> a) -> (r -> b) 

これは、組成物の型シグネチャであり、この組成物は次のとおりです。

instance Functor ((->) r) where 
    fmap = (.) 

ここはfためfmapの型に((->) r)を差し込むことによって(.)fmapのための唯一の可能な実装があることを示すために簡単ですこの型シグネチャを持つ一意の関数。


Data.Functorfmapの中置バージョンとして<$>を定義するので、私たちはここから

(,) <$> sum == fmap (,) sum 
      == (.) (,) sum 

を持って、それは、確かに、結果のタイプがあることを確認するのは比較的簡単で、退屈なしかし、仕事です(Foldable t, Num a) => t a -> b -> (a, b)。 `F <$>のx = FMAP FのX ':私たちは、` `ちょうどfmap`を

(b' -> c') -> (a' -> b') -> (a' -> c') -- composition 
b' -> c' ~ a -> b -> (a,b)    -- first argument (,) 
a' -> b' ~ t n -> n      -- second argument sum 
---------------------------------------------------------------- 
a' ~ t n 
b' ~ a ~ n 
c' ~ a -> b -> (a,b) 
---------------------------------------------------------------- 
a' -> c' ~ t a -> b -> (a,b) 
関連する問題