Как можно использовать функцию экземпляра в Haskell, когда ghc жалуется, что она не входит в область действия, несмотря на импорт?

В Нежное введение в Haskell, версия 98 это говорят:

Instance declarations are not explicitly named in import or export lists. Every module exports all of its instance declarations and every import brings all instance declarations into scope.

Мне это кажется разумным. Во всяком случае, когда я пробую это для fromNumber из экземпляра FromNumber PixelFormat Word32, я сталкиваюсь с ошибкой:

/home/brandon/workspace/hico/src/Hico/Game.hs:269:50: error:
    Variable not in scope:
      fromNumber :: Word32 -> SDL.Video.Renderer.PixelFormat
    |
269 |   let pixFmt :: SDL.Video.Renderer.PixelFormat = fromNumber rawPixFmt
    |      

Тип сообщения об ошибке мне кажется правильным. Мой релевантный импорт:

import qualified SDL                    as SDL 
import qualified SDL.Font
import qualified SDL.Image
import qualified SDL.Internal.Types     (Window(..))
import qualified SDL.Raw
import           SDL.Raw.Video          (getWindowPixelFormat)
import qualified SDL.Video.Renderer     

(особенно последняя строчка с import qualified SDL.Video.Renderer).

Из-за чувства паранойи и поскольку у меня уже была под рукой локальная копия sdl2, я изменил код в SDL2 Renderer.hs и добавил следующие изменения, которые успешно скомпилированы, но показывают, что проблема не в этом:

{-# LANGUAGE InstanceSigs #-}
-- omitted ...
  fromNumber :: Word32 -> PixelFormat
  fromNumber n' = case n' of -- ommited ...

Такое ощущение, что я снова делаю какую-то глупость с импортом, хотя не уверен.

Экспорт экземпляров не подразумевает экспорт определений функций или методов класса. На самом деле в сообщении об ошибке говорится, что переменная не входит в область действия (т.е. вы не импортировали fromNumber как функцию), а не о том, что она не может найти экземпляр. Что произойдет, если у вас import SDL.Internal.Numbered (который, я считаю, является модулем, определяющим fromNumber)?

Bakuriu 17.12.2018 22:57

АаааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааВа оyчке, я пытался добавить квалификаторы по-другому, но это не имело смысла .... это имеет больше смысла, и это работает! Теперь мне нужно будет протестировать проблему времени выполнения, которая возникла у меня позже, но это отвечает на мой вопрос!

bbarker 17.12.2018 23:06

@Bakuriu не возражаете, чтобы ваш комментарий стал ответом?

luqui 18.12.2018 00:23

@luqui Я думаю, что ответ Дэниела предоставляет всю информацию. @bbarker Очевидно, что импортирование пакета с Internal в его имени делать не следует. Но я считаю, что какой-то другой модуль публично реэкспортирует FromNumber, так что вам придется его поискать.

Bakuriu 18.12.2018 08:09
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
128
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Экземпляры глобальны, а сам класс и его методы - нет. Итак, если у вас есть

module X () where
instance Foo Bar where fooBar = undefined

и импортировать X, тогда вы сможете передавать Bar в функции, которые требуют, чтобы их аргументы были экземпляром Foo (или получить Bar обратно из вещей, которые обещают создать экземпляр Foo), но не сможете назвать Foo, Bar , или fooBar самостоятельно, если вы не импортировали их откуда-то еще!

Исправление в вашем случае - найти модуль, который экспортирует fromNumber, например. экспортируя FromNumber(..), и импортируйте его оттуда.

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