Как Haskell оценивает эту функцию, определенную при частичном применении?

Я пытаюсь понять, как Haskell оценивает pp1 [1,2,3,4] получить [(1,2),(2,3),(3,4)] Вот:

1. xnull f [] = []
2. xnull f xs = f xs
3. (/:/) f g x = (f x) (g x)
4. pp1 = zip /:/ xnull tail

Я начинаю так:

a)  pp1 [1,2,3,4] = (zip /:/ xnull tail) [1,2,3,4]  -- (rule 4).
b)  (zip /:/ xnull tail) [1,2,3,4] 
       = (zip (xnull [1,2,3,4]) (tail) [1,2,3,4])   -- (rule 3)
c)  -- I'm not sure how to continue because xnull receives a function 
    -- and a param, and in this case it only receives a param.

Любая помощь?

3 ответа

Решение

Просто продолжайте расширяться:

pp1 [1, 2, 3, 4] = zip /:/ xnull tail $ [1, 2, 3, 4]
                 -- inline (/:/) f g x = f x (g x)
                 --  f = zip, g = xnull tail, x = [1, 2, 3, 4]
                 -- therefore: 
                 = zip [1, 2, 3, 4] (xnull tail $ [1, 2, 3, 4])
                 -- inline the definition of xnull and note that the argument is not null
                 -- so we just want f x, or tail [1, 2, 3, 4]
                 = zip [1, 2, 3, 4] (tail [1, 2, 3, 4])
                 -- evaluate tail
                 = zip [1, 2, 3, 4] [2, 3, 4]
                 -- evaluate zip
                 = [(1, 2), (2, 3), (3, 4)]

Президентство оператора имеет значение. Вы не указали ассоциативность (/:/) так что по умолчанию он был относительно слабым. Следовательно, (xnull tail) связаны крепче, чем (/:/),

Кроме того, как примечание, (/:/) уже существует в стандартной библиотеке как (<*>) от Control.Applicative, Это достаточно общее, так что это может быть трудно увидеть, но Applicative экземпляр для Reader (или, возможно, лучше понимать как функцию Applicative) предоставляет именно этот пример. Это также известно как ap от Control.Monad,

zip <*> tail :: [b] -> [(b, b)]
zip <*> tail $ [1, 2, 3, 4] = [(1, 2), (2, 3), (3, 4)]

Это не верно

b) (zip /:/ xnull tail) [1,2,3,4] = (zip (xnull [1,2,3,4]) (tail) [1,2,3,4]) (rule 3)

потому что это должно быть

b) (zip /:/ xnull tail) [1,2,3,4] = (zip [1,2,3,4] (xnull tail [1,2,3,4])) (rule 3)

Ошибка заключается в чтении zip /:/ xnull tail как в (zip /:/ xnull) tail скорее, чем zip /:/ (xnull tail),

Я знаю, что это немного устарело. Но в любом случае, вот мое взятие..

Это помогает увидеть определение

pp1 =  zip  /:/  xnull tail
    = (zip) /:/ (xnull tail)
    = (/:/) zip (xnull tail)

Обратите внимание на круглые скобки вокруг (xnull tail) с указанием приложения функции, имеющего более высокий приоритет инфиксных операторов.

Теперь определение (/:/) это вернуть другую функцию q это будет аргумент x и вернуть результат применения функции, возвращенной частичным применением ее первого аргумента r к тому, что возвращается от применения его второго аргумента s,

То есть f должно быть в состоянии принять по крайней мере 2 аргумента, в то время как g нужно только взять хотя бы 1.

(/:/) f g = q 
            where
            q x = r s
                  where
                  r = f x
                  s = g x

Обратите внимание, что r является f x, так q x является f x s,

Было бы понятнее написать

f /:/ g = (\x -> f x (g x))

Сейчас дано

pp1 = zip /:/ xnull tail 

мы можем расширить до

pp1 = q
      where
      q x = r s
            where
            r = zip x
            s = xnull tail x

или же

pp1 = (\x -> zip x $ xnull tail x)

Остальное просто заменяет x с [1,2,3,4] и делать оценки.

Другие вопросы по тегам