Объясни мне - PullRequest
       10

Объясни мне

0 голосов
/ 21 мая 2018

Погружаясь в Хаскелл, и пока я наслаждаюсь языком, я нахожу бессмысленный стиль совершенно неразборчивым.Я сталкивался с этой функцией, которая состоит только из этих ASCII-болванов, как показано ниже.

f = (.)(.)

И хотя я понимаю его сигнатуру типа и то, что она делает, я не могу понять, насколько я понимаюпочему это делаетТак что, может, кто-нибудь напишет для меня версию без точечной версии, и, возможно, пошагово вернитесь к сортировке точечной версии, например:

f g x y = (g x) + y   
f g x = (+) (g x)    
f g = (+) . g    
f = (.) (+)

Ответы [ 3 ]

0 голосов
/ 21 мая 2018

Мы можем работать назад "сопоставление с образцом" над определениями комбинаторов.Учитывая

f a b c d =  a b  (c d) 
          = (a b) (c d)

мы продолжаем

         = B (a b) c d 
         = B B a b c d    -- writing B for (.)

, поэтому Эта-сокращение

f = B B 

, потому что

a (b c) = B a b c         -- bidirectional equation

по определению.(.) на Haskell на самом деле является B комбинатором (см. BCKW комбинаторы ).


edit: Потенциально, многие комбинаторы могут совпадатьтот же код.Вот почему существует много возможных комбинационных кодировок для одного и того же куска кода.Например, (ab)(cd) = (ab)(I(cd)) является допустимым преобразованием, которое может привести к совпадению определения другого комбинатора с .Выбор «наиболее подходящего» - это искусство (или поиск в пространстве поиска с довольно высоким коэффициентом ветвления).

Это как раз то, что вы спросили назад .Но если вы хотите пойти «вперед», лично мне нравится комбинаторный подход гораздо лучше, чем лямбда-нотация ерзать.Я бы даже сразу написал много аргументов и в конце избавился бы от лишних:

BBabcdefg = B(ab)cdefg = (ab)(cd)efg 

, следовательно,

BBabcd    = B(ab)cd    = (ab)(cd) 

- это все, что нужно.

0 голосов
/ 22 мая 2018

Вы также можете постепенно добавлять аргументы к f:

f = ((.) . )
f x = (.) . x
f x y = ((.) . x) y
      = (.) (x y)
      = ((x y) . )
f x y z = (x y) . z
f x y z t = ((x y) . z) t
          = (x y) (z t)
          = x y (z t)
          = x y $ z t

Результат показывает, что x и z на самом деле (двоичные и унарные соответственно) функции, поэтому я буду использоватьразные идентификаторы:

f g x h y = g x (h y)
0 голосов
/ 21 мая 2018

Обычно (?) (где ? обозначает произвольный инфиксный оператор) совпадает с \x y -> x ? y.Таким образом, мы можем переписать f как:

f = (\a b -> a . b) (\c d -> c . d)

Теперь, если мы применим аргумент к функции, мы получим:

f = (\b -> (\c d -> c . d) . b)

Теперь b это просто аргумент f, поэтому мы можем переписать это следующим образом:

f b = (\c d -> c . d) . b

Определение . равно f . g = \x -> f (g x).Если заменить внешний . его определением, мы получим:

f b = \x -> (\c d -> c . d) (b x)

Снова мы можем превратить x в обычный параметр:

f b x = (\c d -> c . d) (b x)

Теперь давайте заменим другой .:

f b x = (\c d y -> c (d y)) (b x)

Теперь давайте применим аргумент:

f b x = \d y -> (b x) (d y)

Теперь давайте снова переместим параметры:

f b x d y = (b x) (d y)

Готово.

...