2011-11-08 14 views
1

Imはファンクタが何であるかを理解しようと、私はこのチュートリアル/例が見つかりました:ファンクタに関する混乱のビット?

http://en.wikibooks.org/wiki/Haskell/Solutions/Applicative_Functors

data Tree a = Node a [Tree a] 

上記のタイプであることのためファンクタ:

instance Functor Tree where 
    fmap f (Node a ts) = Node (f a) (map (fmap f) ts) 

すると、誰かが説明するのに役立つことができるもの正確に彼らはやったし、なぜ彼らはそれをやったのですか?私の理解では、ファンクタを使用してデータ型を反復することができます。私は使用する構文を理解するように思われる?

+1

[Typeclassopedia](http://www.haskell.org/wikiupload/e/e9/Typeclassopedia.pdf)は、ファンクターについて学ぶのに適したもう1つの場所です。構文のどの部分が特に問題を引き起こしていますか? –

+0

私はtsは何ですか? – user997112

+0

@ user997112 'ts'は、' [Tree a] '型の' Node'の第2フィールドの値に束縛されているので、 'ts'はそのノードが保持するサブツリーです。 –

答えて

3

Functorは、2つのデータ表現の間のマッピングに役立ちます。時々それは反復に似ていることがあります。この一般的なFunctorのtypeclassを使用すると、データ型(MaybeListTree)の実際の構造を無視して、そのデータにのみフォーカスを当てることができます。そのデータ型の作成者は、そのデータ構造がどのように横断/反復されるのかを知っているので、そのデータ型のインスタンス(Functorの形式)を実装する必要があります。我々が提供しなければならないのは、fという機能があり、それはaになり、bにマップされます。例えば:

import Data.Char (toLower) 

data Tree a = Node a [Tree a] 
    deriving Show 

instance Functor Tree where 
    fmap f (Node a ts) = Node (f a) (map (fmap f) ts) 

main :: IO() 
main = do print (toLower `fmap` (Node 'F' [])) -- Node 'f' [] 
      print (toLower `fmap` (Just 'F')) -- Just 'f' 
      print (toLower `fmap` "FOO")   -- "foo" 

我々はfmap組み合わせる同じコードtoLowerを用いたもの文字を小文字にすることができました。

したがって、Functorインスタンスがパターンマッチングを使用して内部データを抽出し、受け取ったコールバック関数fをこれらの各結果に適用することを定義するときにすべきことは何ですか。

<$>というモジュールには、fmapのインシニックスシノニムがあります。

main :: IO() 
main = do print (toLower <$> (Node 'F' [])) -- Node 'f' [] 
      print (toLower <$> (Just 'F')) -- Just 'f' 
      print (toLower <$> "FOO")   -- "foo" 
3

以前はハスケルを見たことがありませんでしたが、値が入っているノードとツリーの配列からなるデータ型(ツリーと呼ばれます)を定義していると推測しています。元のツリーの枝)。次に、関数とツリーで動作する関数を定義し、その関数をNodeの値に適用し、配列関数内のすべてのブランチに再帰的に適用することで新しいツリーを作成します(ショートカットとしてマップ関数を使用)。

+2

あなたが一度も見たことがないなら。その前にハスケルはとてもうまくいった。 – augustss

+0

@augustssありがとう! – Neil

3

基本的には、Haskellで、あなたにファンクタを考えることができます:

  1. 特別な文脈での値を含むボックス(IO、多分、どちらのa)は、複数の値を保持している
  2. 構造(ツリー、マップ、リスト)

さらに、ファンクタはその特定の構造を理解する操作 - fmapを持っています。

fmapを使用すると、構造体保存変換をファンクタに簡単に適用できます。例えば、fmap (+ 1)は任意のファンクタに1を加算関数である。

Prelude> fmap (+ 1) [1,2 ] -- using a list functor 
[2,3] 
Prelude> fmap (+ 1) (Just 2) -- using a maybe functor 
Just 3 

をあなたが与えてくれた例では、TreeはのFunctorインスタンスを与えている - fmapの実施を - ツリーの構造を理解していますあなたのためにそれを抄録します。

Functors、Appliances Functors、Monads、Monoidsのための素晴らしいリソースはLearn You A Haskellです。

+0

それは基本的にカスタムデータ型の「マップ」を定義していますか? – user997112

+1

@ user997112 - それはそれを見る良い方法です。 'fmap'は' map'の一般化です。 –