2016-06-12 3 views
3

ハスケルでは、fmapを2つの関数に適用することができます。これは基本的に関数の構成です。 fmapを構成して、高いアリティ(fmap . fmap)の関数の関数合成を有効にすることもできます。マップを2つの関数に適用できるようにファンクタを実装するにはどうすればよいですか?

これは関数がファンクタであるために機能します。

このようなファンクタ(または適切なmapメソッド)をJavascriptで実装するにはどうすればよいですか?

これは私がこれまでにしようとしているものです:

funcProto = { 
    map(f) { return y => f(this.x(y)) } 
}; 

function func(x) { 
    return Object.assign(Object.create(funcProto), {x: x}); 
} 

const comp = f => g => x => f(g(x)); 
const map = f => ftor => ftor.map(f); 
const sub = y => x => x - y; 
const sqr = x => x * x; 
const inc = x => x + 1; 

を。これは、通常の関数合成のために働く:

func(sqr).map(inc)(2); // 5 

しかし、それはmapの合成バージョンでは動作しません。

const map2 = comp(map)(map); 
map2(sub)(sub)(10)(5)(4); // Error 

私は自分自身を伝統的な方法にあまりにも多くのファンクタが適応していると思うJavascriptで実装されています。ファンクタとしての機能は、リストとは多分異なる振る舞いをします。

+0

"*伝統的な方法ファンクタはJavascriptで実装されています*" - ありません。 – Bergi

答えて

2

ハスケルでは、すべてが関数です。あなたのJavaScriptで、あなたの関数のいくつかは.x()メソッドを持つfuncと表され、いくつかはネイティブFunctionです。それはうまくいかない。

const sub = y => x => x - y; 
const sqr = x => x * x; 
const inc = x => x + 1; 
const comp = f => g => x => f(g(x)); 
  • プレーン機能、ノー方法:ここで

    は3つのアプローチです。

    Function.prototype.fmap = function(f) { return comp(this)(f); }; 
    console.log(sqr.fmap(inc)(1)); // 5 
    const fmap2 = comp.fmap(comp) // not exactly what you want, works just like above 
    Function.prototype.fmap2 = function(f) { return this.fmap(g => g.fmap(f)); } // better 
    console.log(sub.fmap2(sub)(10)(5)(4)); // 9 
    
  • (もES6で)独自の関数型構築:

    function Func(f) { 
        if (!new.target) return new Func(f); 
        this.call = f; 
    } 
    // Ahem. 
    const sub = Func(y => Func(x => x - y)); 
    const sqr = Func(x => x * x); 
    const inc = Func(x => x + 1); 
    const comp = Func(f => Func(g => Func(x => f.call(g.call(x))))); 
    // Now let's start 
    const fmap = Func(f => Func(x => x.fmap(f))); // a typeclass! 
    Func.prototype.fmap = function(f) { return comp(this)(f); }; // an instance of the class! 
    console.log(fmap.call(inc).call(sqr).call(1)); // 5 
    const fmap2 = comp.call(fmap).call(fmap); 
    console.log(fmap2.call(sub).call(sub).call(10).call(5).call(4)); // 9 
    
+0

'const fmap = comp;'は非常にユーモラスで、質問に答えました。真剣に、 'fmap'と'(。) 'はHaskellで異なる型を持っています。なぜなら、それらが(fmapが2つの関数に適用されて)提供されている理由が分かりました。そして、あなたは 'fmap === comp'と言って、それを処理します。それでは、このコンテキストでは 'fmap'と' comp'の間に実際的な違いはなく、Javascriptのメソッドのために 'comp'バージョンを作るのはほとんど意味がありません。私はこの質問に対してfmapとfunctor、関数がfunctorであるという事実をより深く理解するようにもともと尋ねました。 – ftor

+1

'fmap'は' Functor'型クラスのメソッドであるため、 'Functor'の様々なインスタンス(例えばリストなど)に対して定義されています。そのため、 'fmap'は' .'とは異なる(より一般的な)タイプです。関数の場合、 'fmap'は実際に' .'と一致します。 https://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.Base.html#line-638 (申し訳ありませんが、既に削除されている前のコメントには混乱しました。 ) – FPstudent

0

が私を許しを

const fmap = comp; // for functions only 
console.log(fmap(inc)(sqr)(1)) // 5 
const fmap2 = comp(fmap)(fmap); 
console.log(fmap2(sub)(sub)(10)(5)(4)); // 9 
  • 方法としてfmapを使用して、ネイティブFunction Sを拡張私が間違っているが、あなたは混乱しているように見える場合ハスケルのs。ハスケルでFunctor型クラス(fmapがより正確に)「マップ」のデータ型を表す定義されている:例えば

    https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor.html

    、リスト(ハスケルで[])のように、Functorのインスタンスです。

    fmap (\x->x+1) [1,2,3] -- returns [2,3,4] 
    

    上記マニュアルで指定された、fmap (f . g)fmap f . fmap gと同等でなければならないことは事実であるように(ハスケルで.関数組成物を意味し、それは、であることを思い出してくださいはf(g(x))と等しくなります)。例えば、

    f x = x + 1 
    

    をしましょうと。そして、

    g y = y * 2 
    

    fmap (f.g) [1,2,3] -- equivalent to [(f.g) 1, (f.g) 2, (f.g) 3] 
    

    (fmap f . fmap g) [1,2,3] -- equivalent to (fmap f (fmap g [1,2,3])) 
    

    は等価であり、両方が[3,5,7]を返します。

    Arrayは、を持っているため、この意味ではすでにFunctorです。

    const f = x => x + 1; 
        const g = y => y * 2; 
        const comp = f => g => x => f(g(x)); 
        const fmap_array = f => a => a.map(f); 
    
        fmap_array (comp(f)(g)) ([1,2,3]); // [3,5,7] 
        (comp (fmap_array(f)) (fmap_array(g))) ([1,2,3]); // [3,5,7] 
    

    それとも、あなたが好きならば、あなたがこれを行うことができます:

    Array.prototype.fmap = function(f) { return this.map(f); } 
        [1,2,3].fmap(f); // [2,3,4] 
        [1,2,3].fmap(g); // [2,4,6] 
        [1,2,3].fmap(comp(f)(g)); // [3,5,7] 
        [1,2,3].fmap(g).fmap(f); // [3,5,7] 
    

    P.S.何かのために

    https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor.html#control.i:ic:Functor:Functor:28

    https://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.Base.html#line-638

    :確かに関数合成fmap f g = (f . g)として定義され、またFunctorのインスタンスです機能(Haskellでは->を) -

    は今、私はあなたがあなたの質問に何を意味するか見ますJavaScriptでも同様です。

    const fmap_func = f => g => comp(f)(g); // or "const fmap_func = comp;"! 
        fmap_func(f)(g)(42); // 85 
    

    、またはもう一度好きな場合:

    Function.prototype.fmap = function(f) { return comp(f)(this); }; 
        g.fmap(f)(42); // 85 
    
  • +1

    Haskellで2つの関数を 'fmap'と組み合わせると'(。) 'と同じ結果になります([この質問を参照](http://stackoverflow.com/questions/27883414/difference-between-function- composition-operator-and-fmap))。そして、あなたがそれを作成すると( 'fmap。fmap')、それは'(。)。(。) '([この回答を参照](http://stackoverflow.com/a/5822395))のように振る舞います。なぜ私はJavascriptでこのような 'fmap'を実装しようとしたのかをより良く理解するためです。しかし、これは意味がないことが分かりました。なぜなら、 'fmap'(2つの関数と組み合わされた)と' comp'はJavascriptでは事実上同じだからです。 – ftor

    +0

    これを入手しました - 私はP.S.を追加しました。 – FPstudent

    関連する問題