#haskell #pointfree
#хаскелл #без точек
Вопрос:
Вот функция, которая умножает первые два элемента трехэлементного кортежа:
f (a, b, _) = a * b
Мне было любопытно, можно ли сделать эту функцию бесточечной. Для пары это было бы так же просто, как f = uncurry . (*)
, и если бы у нас было что-то подобное tripleToPair
, это сделало бы решение очевидным, но эта функция также написана самым простым способом, с помощью сопоставления с образцом.
Я спросил всемогущего pointfree.io , но он вернул ошибку 500. Возможно ли это вообще? Вопрос чисто теоретический, на мой взгляд, функция хороша и так.
Комментарии:
1. При переходе к без точек мы обычно выбираем разрешенный набор примитивов. «Обычный» набор примитивов имеет дело только с парами. Например, почему у нас есть
curry/uncurry
только функции с 2 аргументами, а не вообще? В некоторых языках тройка представлена как вложенная пара(a,(b,c))
, и там достаточно иметь дело с парами, чтобы быть общим, но Haskell использует совершенно другой тип для повышения эффективности, поэтому, я думаю, нам нужно разрешить еще несколько примитивов в нашем преобразовании без точек.
Ответ №1:
Самый простой способ — использовать liftA2
(ab) Applicative
экземпляр для функций
import Control.Applicative
-- This two functions are defined in module Data.Tuple.Extra from extra package
-- You could use lenses too, I guess
fst3 (a,_,_) = a
snd3 (_,b,_) = b
f = liftA2 (*) fst3 snd3
Комментарии:
1. Я думал, что с использованием базового пакета может быть какая-то магия, но это приятно. Имея
extra
, мы тоже могли бы сделатьf = uncurry3 (const .) . (*)
, но это менее элегантно.