0

次のタイプを手動で派生させたい:

f1 x xs = (filter . (<)) x xs

を初めて見xたので、次のようになります。

x :: t1

次に(<)、このタイプがあります:

(<) :: Ord a1 => a1 -> a1 -> Bool

(< x)次のタイプを統合できる場合にのみ言えます。

t1  ~  a1

それで

x :: a1

そう

(<x) :: Ord a1 => a1 -> Bool

フィルタにはこのタイプがあります

filter :: (a2 -> Bool) -> [a2] -> [a2]

xs を見るのは初めてなので、

xs :: t2

(filter . (<)) x xs次のタイプを統合できる場合にのみ言えます。

a1 -> Bool ~ a2 -> Bool
t2  ~ [a2]

したがって、正しいタイプが(GHCiに尋ねる)の場合f1 :: (a2 -> Bool) -> [a2] -> [a2]、 と同じタイプのが得られます。filterOrd a => a -> [a] -> [a]

何か助けはありますか?

4

2 に答える 2

3

与えられた式をトップダウンで処理できます。このように、何がどこにあるのかを推測する必要はありません。派生は純粋に機械的に行われ、エラーの余地は最小限に抑えられます。

f1    x   xs = (filter . (<)) x xs
f1    x   xs :: c                        (filter . (<)) x xs :: c
f1    x :: b -> c                        xs :: b
f1 :: a -> b -> c                        x  :: a 

(filter .  (<)) x      xs  :: c
filter    ((<)  x)  ::  b  -> c          c ~ [d] , b ~ [d]
filter :: (d->Bool) -> [d] -> [d]        (<) x :: d -> Bool

(<) :: (Ord a) => a -> a -> Bool
(<)               x :: d -> Bool         a ~ d , (Ord a)

f1  :: (Ord a) => a -> [a] -> [a]

これに取り組む別の方法は、 の定義でeta リダクションf1を実行できることに注意することです。

f1    x   xs = (filter . (<)) x xs
f1           = (.) filter (<)

(.) :: (   b      ->     c     ) -> (           a ->   b      ) -> (a->c)
(.)             filter                           (<)            ::   t1
(.) :: ((d->Bool) -> ([d]->[d])) -> ((Ord a) => a -> (a->Bool)) ->   t1

        b ~ d -> Bool , c ~ [d] -> [d] , t1 ~ a -> c , (Ord a)
        b ~ a -> Bool
        -------------
            d ~ a

f1 :: t1 ~ (Ord a) => a -> c 
         ~ (Ord a) => a -> [d] -> [d]
         ~ (Ord a) => a -> [a] -> [a]

もちろん、型の矢印の正しい結合性を使用します:a -> b -> cは実際にはa -> (b -> c)です。

また、型の派生に一般的なスキームを使用します

f    x    y    z :: d
f    x    y :: c -> d      , z :: c
f    x :: b -> c -> d      , y :: b
f :: a -> b -> c -> d      , x :: a
于 2014-04-27T21:29:02.300 に答える