Не удается реализовать экземпляр Foldable из-за неправильного вида - PullRequest
2 голосов
/ 10 ноября 2019

Я изучаю haskell и пытаюсь создать красивую программу для печати. В какой-то момент я хочу получить длину строки (то есть количество столбцов в этой строке). Чтобы иметь возможность сделать это на моем типе данных, я понимаю, что должен реализовать Foldable, который опирается на Monoid.

Ранее моя строка была просто псевдонимом типа для списка, но ради обучения я хочу сделать этот шаг

    import System.IO
    import System.Directory
    import Control.Monad
    import Data.Maybe
    import Data.Monoid
    import Data.Foldable
    import Data.Functor
    import Data.List.Split

    type Field = String
    data Row = Row [Field]

    instance Monoid Row where
        mempty = Row []


    instance Foldable Row where
        foldMap f (Row fs) = foldMap f fs

Но я получаю следующую ошибку компилятора (на ghci 8.0.2)

main.hs:20:19: error:
    • Expected kind ‘* -> *’, but ‘Row’ has kind ‘*’
    • In the first argument of ‘Foldable’, namely ‘Row’
      In the instance declaration for ‘Foldable Row’

Теперь я не знаю, что это за тип данных. Я ожидал, что это будет просто отложить до единственного свойства строки типа List

Ответы [ 2 ]

4 голосов
/ 10 ноября 2019

Когда у нас есть Foldable T, T должен быть параметрическим типом, то есть мы должны иметь возможность формировать типы T Int, T String и т. Д.

ВНа Haskell мы пишем T :: * -> * для «типа, параметризованного над типом», поскольку он напоминает функцию от типов к типам. Синтаксис * -> * называется kind of T.

В вашем случае Row не параметризован, это простой тип, что-то вроде *,не * -> *. Итак, Foldable Row - добрая ошибка. В некотором смысле, складываемый объект должен быть универсальным контейнером, подобным списку, а не тем, в котором есть только Field, как в вашем случае.

Вы можете вместо этого определить data Row a = Row [a] и использоватьRow Field когда вам нужен конкретный случай.

В качестве альтернативы, вы можете попробовать MonoFoldable Row из пакета mono-traversable, но учтите, что это более продвинутый вариант, включающий семейства типов. Не пренебрегайте этим путем, прежде чем рассматривать его последствия. В конечном итоге все сводится к , почему вам нужен Foldable экземпляр.

0 голосов
/ 11 ноября 2019

что такое "вид" типа данных?

Типы "вида *" - это типы вещей, которые могут появляться впрограмма на Haskell .

Пример: Int.

Не пример: Maybe.

a :: Int ; a = 1 может появиться в программе на Haskell, но b :: Maybe ; b = Just 1 не может. Оно должно быть b :: Maybe Int ; b = Just 1, чтобы оно могло отображаться в программе на Haskell.

Что такое Maybe Int? Это тип *, такой же, как Int. Так что же такое Maybe? Это тип вида * -> *. Поскольку Maybe Maybe является также недействительным.

Тип t, следующий за Maybe, должен сам по себе быть *, чтобы Maybe t был *. Таким образом, тип Maybe равен * -> *.

Теперь Haskell называет тип * новым именем, Type. Называть его Thing или как-то более интуитивно понятным.

...