2017-01-11 10 views
0

ハスケルの関数の構成を理解しようとしています。ハスケル複合関数の構成

ZVON http://zvon.org/other/haskell/Outputprelude/filter_f.html
によると、フィルタ関数には2つの引数、bool関数とリストが必要です。

filter (>5) [1,2,3,4,5,6,7,8]が5を超えるものを返す: [6,7,8]

質問、どのようにいくつかの機能の組成物と次の行が利用するフィルタのブール値を渡していますか?

map fst . filter snd . assocs . soeA

それは地図FSTすべきではありません。フィルタ(== True)snd。 assocs。 soeAの各アレイ素子にどういうわけassocs . soeA $ 9戻り [(0,False),(1,False),(2,True),(3,True),(4,False),(5,True),(6,False),(7,True),(8,False),(9,False)]

soe 9戻り[2,3,5,7]

ブール値が使用されているが、私は、組成物の最初の二つの機能を実行し、引数を渡す分析するsoeA

この構成がどのように機能しているかを説明する助けは非常に高く評価されるでしょう。

完全なコードは次のとおりです。 `

module FastSeive where 

import Control.Monad 
import Control.Monad.ST 
import Data.Array.ST 
import Data.Array.Unboxed 



soeST :: forall s. Int -> ST s (STUArray s Int Bool) 
soeST n = do 
    arr <- newArray (0, n) True 
    mapM_ (\i -> writeArray arr i False) [0, 1] 
    let n2 = n `div` 2 

    let loop :: Int -> ST s() 
     loop i | i > n2 = return() 
     loop i = do 
      b <- readArray arr i 

      let reset :: Int -> ST s() 
       reset j | j > n = return() 
       reset j = writeArray arr j False >> reset (j + i) 

      when b (reset (2*i)) 

      loop (succ i) 

    loop 2 
    return arr 


soeA :: Int -> UArray Int Bool 
soeA n = runST (soeST n >>= freeze) 


soe :: Int -> [Int] 
soe = map fst . filter snd . assocs . soeA 


soeCount :: Int -> Int 
soeCount = length . filter id . elems . soeA 

`

答えて

0

短い答えは次のとおりです。ここで、sndBool -returning機能filterを期待です。あなたが書いた表現では:map fst . filter (==True) snd . assocs . soeAsndfilterの第2引数で、(==True)が最初の引数になります。もちろん、filterはすでに2つの引数に適用されており、関数合成では使用できないため型チェックされません。それはもはや関数ではありません。長い答えを


、我々は実際には「何が起こっているかを調べるための定義:

(f . g) x = f (g x) 
-- In haskell, it is defined as being right associative 

-- Meaning that if we put explicit parenthesises, we'd have: 
soe = (map fst . (filter snd . (assocs . soeA))) 
-- That only really matters for the compiler, though, 
-- because we know function composition is associative. 

soe = map fst . filter snd . assocs . soeA 
-- "Un-pointfree-ing" it: 
soe x = (map fst . filter snd . assocs . soeA) x 
-- Applying (.)'s definition: 
soe x = map fst ((filter snd . assocs . soeA) x) 
-- Again: 
soe x = map fst (filter snd ((assocs . soeA) x)) 
-- And again: 
soe x = map fst (filter snd (asocs (soeA x))) 

それはsndfilterであることが明らかだ」(.)を適用することができます2番目の引数がしますが、sの最初の引数assocs (soeA x)が評価するものを評価してください。次の結果に

次いでつ f . g . hを書き込むときに、これが最初の結果に g次いで、その引数に hを適用する関数として、右から左へ読み取ることができるより一般

f、および収率最終値。


ここで、より長い回答については、式のタイプが推測される方法を見ていきます。 sndBool - 返す関数filterが、snd :: (a, b) -> bのタイプシグニチャを持っているにもかかわらず、なぜそうであるかがわかります。

免責事項:コンパイラエンジニアリングの背景はありません。私が使用している用語は不正確かもしれません。

filterのタイプは(a -> Bool) -> [a] -> [a]です。 sndのタイプは(a, b) -> bです。

これらは実際にはパラメータ化された型です。私たちは、型パラメータを明示的に行うことができます:

filter :: forall a. (a -> Bool) -> [a] -> [a] 
snd :: forall a b. (a, b) -> b 
我々はまた、我々は次の書くつもり何でそれが非曖昧にするために filterの型引数の名前を変更します

filter :: forall c. (c -> Bool) -> [c] -> [c] 

filterを取得最初にsndに適用されます。ですから、c -> Boolfilterから(a, b) -> bsndのタイプで試してみることができます。私たちは、これらの式を得る:

c -> Bool = (a, b) -> b 

=== 

c = (a, b) 
b = Bool 

=== 

c = (a, Bool) 
b = Bool 

我々はassocs (soeA x)のタイプが[(Int, Bool)]であると仮定します。 filterの第2引数はタイプ[c]を持っているので、我々はさらに統一することができます:

[c] = [(Int, Bool)] 

=== 

c = (Int, Bool) 

をこれも私たち与える:

(Int, Bool) = c = (a, Bool) 

=== 

a = Int 

ので、タイプのアプリケーションの後、我々はサブのためにこれらの具体的な種類を取得します表現:

filter :: ((Int, Bool) -> Bool) -> [(Int, Bool)] -> [(Int, Bool)] 
snd :: (Int, Bool) -> Bool 

まあ、もちろん、我々はどちらかGHCiのを使用して、またはテキストエディタのHaskellのプラグを介して、そのことについて私たちに伝えるために、すべてに沿ってGHCの型推論を使用している可能性がに。

+0

ありがとうございました。 "soe x = map fst(filter snd((assocs。soeA)x))") "本当に助けになった – brander