Haskell fmap для пользовательского типа данных - PullRequest
0 голосов
/ 23 мая 2018

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

data StructureA = StructureA [Int] Bool Int
data StructureB = StructureB [String] String

Моя цель состоит в том, чтобы отобразить функции на массивы, содержащиеся внутри экземпляров таких типов данных

inst = StructureA [1,1,1] True 0
fmap (+1) inst -- [2,2,2]

Мои начальныерешение выглядит следующим образом

instance Functor StructureA where
    fmap (StructureA arr _ _) = fmap arr

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

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

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Конструктор типа может быть только функтором, если он имеет ровно один параметр.Конструктор типа StructureA вообще не имеет параметра типа и поэтому не может быть функтором.

0 голосов
/ 23 мая 2018

Вы можете объявить экземпляр Functor только для параметризованного типа (точнее, * -> *): тип, который все еще нуждается в дополнительном (и ровно одном) параметре типа.

Итак, сначала нам нужно ввести параметр типа.Даже если вы никогда не планируете использовать что-то еще, кроме Int s, мы можем легко абстрагироваться от этого:

data Structure <b>a</b> = Structure [<b>a</b>] Bool Int

Мы можем, например, объявить StructureA как синомим типа :

type StructureA = Structure Int

Теперь мы можем сделать его экземпляром Functor, написав:

instance Functor <b>Structure</b> where
    fmap f (Structure as b c) = ...

Обратите внимание, что мы здесь не пишем (Structure a), но Structure, поскольку, как мы уже говорили, fmap может свободно изменять тип, над которым работает коллекция: функция f может иметь, например, тип Int -> Char для преобразования Structure Int вStructure Char.

Теперь нам еще нужно реализовать fmap.fmap имеет тип fmap :: Functor f => (a -> b) -> f a -> f b, что означает, что он принимает функцию, и в данном случае Structure a, и создает Structure b.Исходя из вашего вопроса (и принятых нами проектных решений), единственная часть, которую мы можем отобразить, это первый параметр, поэтому мы создаем новый Structure, где второй параметр является результатом fmap f, но затемвторой параметр, так:

instance Functor Structure where
    fmap f (Structure as b c) = <b>Structure (fmap f as) b c</b>
...