Что не так с моим импортом / использованием конструктора данных, когда ghc предлагает добавить конструктор в список импорта?

У меня есть следующая строка кода, в которой я пытаюсь извлечь внутренний необработанный тип, чтобы я мог работать с ним напрямую:

SDL.Internal.Types.Window (rawWindow) = window

Мой импорт выглядит так:

import qualified SDL.Internal.Types     (Window)

Ошибка, которую я получаю, приведена ниже; кажется, я уже делаю то, что он предлагает.

%    /home/brandon/workspace/hico/src/Hico/Game.hs:273:5: error:
        Not in scope: data constructor `SDL.Internal.Types.Window'
        Perhaps you want to add `Window' to the import list
        in the import of `SDL.Internal.Types' (src/Hico/Game.hs:34:1-48).
        |
    273 |     SDL.Internal.Types.Window (rawWindow) = window
        |     ^^^^^^^^^^^^^^^^^^^^^^^^^

Содержимое файла Types.hs очень короткое и, похоже, не дает мне никаких подсказок:

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneriC#-}
module SDL.Internal.Types
  ( Joystick(..)
  , Window(..)
  , Renderer(..)
  ) where

import Data.Data (Data)
import Data.Typeable
import GHC.Generics (Generic)

import qualified SDL.Raw as Raw

newtype Joystick = Joystick { joystickPtr :: Raw.Joystick }
  deriving (Data, Eq, Generic, Ord, Show, Typeable)

newtype Window = Window (Raw.Window)
  deriving (Data, Eq, Generic, Ord, Show, Typeable)

-- | An SDL rendering device. This can be created with 'SDL.Video.createRenderer'.
newtype Renderer = Renderer Raw.Renderer
  deriving (Data, Eq, Generic, Ord, Show, Typeable)
Стоит ли изучать 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
0
143
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Написав

import qualified SDL.Internal.Types     (Window)

вы импортируете только тип Window и ни один из его конструкторов. Чтобы импортировать тип данных и некоторое ограниченное подмножество его конструкторов, нужно записать (используя в качестве примера Maybe, потому что я не знаю типов SDL):

import Prelude (Maybe(Just))

Этот импорт позволит вам использовать Maybe в аннотациях типов и использовать конструктор Just для сопоставления с образцом или для создания новых значений типа Maybe a, но вы не сможете использовать Nothing ни в одном из этих обстоятельств.

Обратите внимание, что описанное выше было бы очень необычным делом: обычно вам нужны либо все конструкторы типа (чтобы вы могли создавать и использовать любое значение этого типа), либо ни один из них (чтобы ваши функции могли получать или возвращать значения этого типа, созданные и потребляемые другими функциями).

Если вам нужны все конструкторы типа, вы можете использовать точный синтаксис, используемый в указанном вами определении экспорта модуля: (..) означает «все конструкторы этого типа»:

import qualified SDL.Internal.Types     (Window(..))

Я настоятельно рекомендую либо экспортировать / импортировать конструкторы все (с использованием синтаксиса (..)), либо их никто, за исключением очень необычных обстоятельств. Ограничение только некоторыми из них предполагает использование частичных функций, а их явное перечисление - это просто дополнительная работа заранее и при изменении типа. Единственный раз, когда я мог бы рассмотреть возможность экспорта только некоторых конструкторов, было бы, если бы другие использовались временно для внутренних целей, как в некоторых формулировках красно-черных деревьев.

dfeuer 17.12.2018 19:48

@dfeuer Действительно. Я отредактировал вопрос, чтобы указать, что довольно странно импортировать подмножество конструкторов.

amalloy 17.12.2018 20:08

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