Не в области: конструктор данных в Haskell

Скажите, пожалуйста, в чем проблема?

data Stack' v = Stack' [v] Int deriving (Show)
...
type StackInt = Stack' Int 

main = print(StackInt [1,2,3] 4)

Ошибка, которую я получаю,

Not in scope: data constructor `Stackint'

Что не так?

Ответ 1

Мне кажется, что вы путаете понятия типов и конструкторов, это общая проблема, поскольку они живут в отдельных пространствах имен и часто получают одно и то же имя. В выражении Haskell

data SomeType = SomeType Int

скажем, вы фактически определяете тип SomeType и конструктор SomeType. Тип не является функцией в обычном смысле, но конструктор. Если вы спросите ghci о типе SomeType, вы получите следующее:

:t SomeType
SomeType :: Int -> SomeType

Теперь объявление type является просто сокращением для более длинного определения типа, в вашем случае делая StackInt синонимом Stack' Int. Но для построения значения этого типа вам все равно нужно использовать конструктор Stack' (который имеет тип [v] -> Int -> Stack' v). Таким образом, ваш код должен быть

data Stack' v = Stack' [v] Int deriving (Show)

main = print(Stack' [1,2,3] 4)

Если вы хотите убедиться, что тип был Stack' Int, вы можете добавить функцию

data Stack' v = Stack' [v] Int deriving (Show)

stackInt :: [Int] -> Int -> Stack' Int
stackInt list i = Stack' list i

main = print(stackInt [1,2,3] 4)

EDIT: Я также не написал stackInt list i = Stack' list i для прозрачности здесь, но вы можете написать его более элегантно, как stackInt = Stack'. Это ограничение типа, которое гарантирует, что вы получите правильный тип здесь.

Вы могли бы также иметь как новую функцию, так и синоним типа, если хотите, т.е.

data Stack' v = Stack' [v] Int deriving (Show)
type StackInt = Stack' Int

stackInt :: [Int] -> Int -> StackInt
stackInt list i = Stack' list i

main = print(stackInt [1,2,3] 4)

Ответ 2

Имя конструктора Stack', а не StackInt. Создание псевдонима типа с помощью type не создает псевдоним для конструкторов (что не имеет смысла, поскольку для типа может быть много конструкторов, и их имена не обязательно должны быть связаны с именем типа вообще).

Ответ 3

Нет конструктора данных Stackint. Stackint, как определено вашим объявлением type, является конструктором типа.

Конструктор данных, как и для Stack', Stack', хотя благодаря синониму типа он будет иметь тип Int -> Stack' Int вместо a -> Stack' a.