Область видимости Haskell в определениях вложенных функций, где

StackOverflow https://stackoverflow.com/questions/1819575

Вопрос

У меня проблема с областью действия 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 может принимать любой тип

f1 :: Eq a = > а - > [А]

Несмотря на то, что это локальная функция, вы обобщили эту функцию, чтобы иметь возможность принимать тип, который не существует в f, независимо от того, получает ли эта функция HAS от f, поэтому сигнатура типа не требуется.

Просто удалите подпись типа f1.

Редактировать: прочитайте мой пост обратно, это немного неясно. a в f1 является параметризованным типом, который может принимать что угодно, но передаваемые ему аргументы уже связаны в f. Таким образом, эта функция может получать только то, что получает ее родительская функция, подпись типа, которую вы ей даете, нарушает это правило. Надеюсь, это немного яснее.

Другие советы

Дэйв прямо выше. Еще один способ думать о том, что хотя обе ваши сигнатуры типов ссылаются на переменную 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 ]

и это будет нормально работать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top