5

それでは、要点をまっすぐにしましょう。

:t (map.foldr)
(map.foldr) :: (a1 -> a -> a) -> [a] -> [[a1] -> a]

[[a1]-> a]とは何ですか?私は本当にこの構成を理解しようとしているので、私はこれをしていました:

-- map.foldr

    map.foldr :: (a1 -> a -> a) -> [a] -> [[a1] -> a]

    map :: (a1 -> b1) -> [a1] -> [b1]
    (.) :: (y -> w) -> (x -> y) -> x -> w
    foldr :: (a -> b -> b) -> b -> [a] -> b

    y = (a1 -> b1)      w = ([a1] -> [b1])
    x = (a -> b -> b)   y = (b -> [a] -> b)

    y = (a1 -> b1)  
    y = (b -> [a] -> b)
_________________________

この時点で何が起こりますか?ありがとうございました!

4

3 に答える 3

15

この質問に答えるには、何をして何foldrをするかを思い出すのが良いmapでしょう。

2つのうち、より複雑なのはfoldr

--              list to be folded
--                              v
foldr :: (a -> b -> b) -> b -> [a] -> b
--             ^          ^
--folding function        terminal value

折りたたまれるリストは、実際には一連のコンス(:)とターミナルの空のリストです。

1 : 2 : 3 : []

のアクションは、コンストラクターとコンストラクターをそれぞれフォールディング関数とターミナル値にfoldr置き換えることです。:[]

foldr (+) 0 (1 : 2 : 3 : []) == 1 + 2 + 3 + 0

map関数はより単純です。それを考える1つの方法は、関数とリストを取得し、その関数をリストのすべての引数に適用することです。

map :: (a -> b) -> [a] -> [b]
--        ^         ^
-- function         list

ただし、関数を取得し、代わりにリストに作用する関数として持ち上げることもできます。

map :: (a -> b) -> ( [a] -> [b] )
--        ^              ^
-- function              function on lists

これら2つの機能を構成するとはどういう意味map . foldrですか?これは関数を次々に適用しているだけであることに注意してください-特に、

(map . foldr) f == map (foldr f)

最初に適用するのでfoldr、それを関数に適用する必要があり、f :: a -> b -> b別の関数を取得します。

foldr f :: b -> [a] -> b
--         ^     ^
--terminal val   list to be folded

次に、を適用しますmap。これにより、リストに作用する関数が持ち上げられます。

map (foldr f) :: [b] -> [[a] -> b]
--                ^          ^
--list of terminal vals      functions that fold lists

このタイプは奇妙に見えますが、有効です。ここで、単一の端末値の代わりに、端末値のリストを指定すると、折り返し関数のリストが返されます(指定した端末値ごとに1つ)。


明確にするために、(+)タイプを持つ特定の関数、を見ることができます。

(+) :: Num a => a -> a -> a

これを上記の式に代入すると、次のようになります。

(map . foldr) (+) :: Num a => [a] -> [[a] -> a]
--                             ^          ^
--         list of terminal vals          functions that fold lists

これをリスト[0, 1, 2]に適用すると、次の3つの関数のリストが得られます。

(map . foldr) (+) [0,1,2] :: Num a => [[a] -> a]

このイディオムを使用してmap ($x)、リスト内の各関数を特定の引数に適用できます。それは数字のリストでなければなりません、そして私はを選びます[3,4,5]。注意深く見てください:

> map ($[3,4,5]) ((map.foldr) (+) [0,1,2])
[12, 13, 14]

リスト[3,4,5]は、折りたたみ関数としてを使用して3回折りたたま(+)れ、そのたびに異なる端末値が使用されました。

3 + 4 + 5 + 0 == 12
3 + 4 + 5 + 1 == 13
3 + 4 + 5 + 2 == 14

最終値が0、の場合、値の合計を取得するだけです3 + 4 + 5 == 12。最終値がの場合、値の合計( )1より1つ多くなり、最終値がの場合、値の合計()より2つ多くなります。13214

于 2013-02-02T21:26:17.573 に答える
2

中断したところから続行するには、の2つの定義yが等しくなければなりません。

y = (a1 -> b1) = (b ->  [a] -> b)
               = (b -> ([a] -> b))

したがって、次のように結論付けることができます。

a1 = b
b1 = [a] -> b

関数合成には2つの関数引数が提供されているため、結果の型は次のようになります。

x -> w

しかし、私たちは知っています:

x = a -> b -> b
w = [a1] -> [b1] = [b] -> [[a] -> b]

したがって、結果のタイプは次のとおりです。

(x -> w) = ((a -> b -> b) -> ([b] -> [[a] -> b]))
         =  (a -> b -> b) ->  [b] -> [[a] -> b]

これは次のように一致します:

(a1 -> a -> a) -> [a] -> [[a1] -> a]
于 2013-02-02T20:51:25.827 に答える
1
map.foldr :: (a1 -> a -> a) -> [a] -> [[a1] -> a]

map :: (a1 -> b1) -> [a1] -> [b1]
(.) :: (y -> w) -> (x -> y) -> x -> w
foldr :: (a -> b -> b) -> b -> [a] -> b

-- if you substitute: x = (a -> b -> b)   y = (b -> [a] -> b)
-- then you get for map :: (b -> ([a] -> b)) -> [b] -> [[a] -> b]
-- so if composition operator applied:
map . foldr :: (a -> b -> b) -> [b] -> [[a] -> b]
于 2013-02-02T19:31:14.647 に答える