Хаскель: почему f1 . f2 xy не работает?
Я немного запутался в отношении оператора точка. У меня есть следующий код (для тестирования):
test :: Int -> Int -> Int
test x y = f1 . f2 x y
where f1 n = n+1
f2 x' y' = x' * y'
И я подумал, что сначала он выполнит (f2 x y), а затем f1 для этого результата, но вместо этого он выдаст ошибку. Может ли кто-нибудь сказать мне точное определение оператора точки и что равно f1. f2 xy? (когда написано без оператора точки)
С наилучшими пожеланиями, Skyfe.
РЕДАКТИРОВАТЬ: Если оператор точка дает совершенно новую функцию, я подумал, что следующий код должен работать:
test :: Int -> Int -> Int
test x y = f1 . f2 x
where f1 n = n+1
f2 x' y' = x' + y'
Но и этот код возвращает ошибку.
3 ответа
Инфиксные операторы всегда имеют более низкий приоритет, чем приложения функций в Haskell, так что это
f1 . f2 x
разбирает как это
f1 . (f2 x)
но, f2 x
не относится к функции типа (ну, это может быть, если f2 возвращает функцию, но это не так вообще или в вашей проблеме). Поскольку (.) Действует на функции, это не сработает.
Используйте вместо ($)
f1 $ f2 x
(Я думаю, что другие ответы придумали $
слишком быстро)
Как ты уже знаешь,
f1 . f2 x
анализируется как
f1 . (f2 x)
Написать
(f1 . f2) x
вместо этого делать то, что он читает: сочинять f2
а также f1
а затем применить эту составную функцию к x
, Сейчас
($) :: (a -> b) -> a -> b
f $ x = f x
Похоже, это лишнее. Его основная цель состоит в том, чтобы он имел самый низкий приоритет, поэтому вы можете избежать скобок:
foo . bar . baz $ x + y * z = (foo . bar . baz) (x + y * z)
Смотрите также: Haskell: разница между. (точка) и $ (знак доллара)
Один общий подход состоит в том, чтобы объединить (.)
с ($)
:
f1 . f2 $ x
Это может быть легко расширено для создания более длинных "конвейеров":
f1 . f2 . f3 . f4 $ x
и затем, если вам понадобится такая же комбинация в другом месте, вам нужно только вырезать и вставить:
fs = f1 . f2 . f3 . f4
... fs x ... fs y