Область видимости Haskell в определениях вложенных функций, где
-
10-07-2019 - |
Вопрос
У меня проблема с областью действия Haskell в определениях , где
. Когда у меня есть следующая функция f
, где я хочу передать x
локально определенной функции f1
без явного использования ее в качестве параметра, Я получаю сообщение о том, что тип x
несовместим с типом в выводе f1
, хотя он должен быть таким же:
f :: Eq a => a -> [a] f x = f1 x where f1 :: Eq a => a -> [a] f1 y = [ x, y ]
Ошибка следующая:
Couldn't match expected type `a1' against inferred type `a' `a1' is a rigid type variable bound by the type signature for `f1' at test.hs:4:11 `a' is a rigid type variable bound by the type signature for `f' at test.hs:1:8 In the expression: x In the expression: [x, y] In the definition of `f1': f1 y = [x, y] Failed, modules loaded: none.
Когда я передаю x
в качестве дополнительного параметра, как я делал в следующем коде с функцией g
, он работает нормально:
g :: Eq a => a -> [a] g x = g1 x x where g1 :: Eq a => a -> a -> [a] g1 x y = [ x, y ]
Есть ли способ сделать тип a
в f
совместимым с типом a
(или a1
) в f1
?
Решение
Проблема с вашим кодом - локальная подпись типа f1. Он указывает, что f1 может принимать любой тип
Несмотря на то, что это локальная функция, вы обобщили эту функцию, чтобы иметь возможность принимать тип, который не существует в f, независимо от того, получает ли эта функция HAS от f, поэтому сигнатура типа не требуется. р>
Просто удалите подпись типа f1. Редактировать: прочитайте мой пост обратно, это немного неясно. a в f1 является параметризованным типом, который может принимать что угодно, но передаваемые ему аргументы уже связаны в f. Таким образом, эта функция может получать только то, что получает ее родительская функция, подпись типа, которую вы ей даете, нарушает это правило. Надеюсь, это немного яснее. f1 :: Eq a = > а - > [А] код> р>
Другие советы
Дэйв прямо выше. Еще один способ думать о том, что хотя обе ваши сигнатуры типов ссылаются на переменную a
, на самом деле это не одна и та же переменная типа. В нотации простого числа Хаскелла обе подписи могут быть записаны более явно как:
Это означает, что для обеих функций они могут принимать аргументы любого типа (в уравнении). Это явно не тот случай. В стандартном Haskell 98 единственный вариант - отказаться от подписи типа для и это будет нормально работать. для а. Уравнение = > а - > [А] код> р>
f1
. Но GHC (и другие?) Поддерживают лексически переменные типа scoped . Чтобы вы могли написать {-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. Eq a => a -> [a]
f x = f1 x
where
f1 :: a -> [a]
f1 y = [ x, y ]