Как добавить ограничения класса типов в выражение нового типа? - PullRequest
0 голосов
/ 12 октября 2018

Я читаю книгу Программирование на Haskell из первых принципов , и в главе newtype есть упражнение, в котором меня просят сделать экземпляр TooMany для (Num a, TooMany a) => (a, a).

* 1007.* Упражнения до этого уже сделали TooMany примеров для Int, Goats Int, (Int, String) и (Int, Int).Я сделал это, но не для (Num a, TooMany a) => (a, a).

Все коды следующие:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}

class TooMany a where
  tooMany :: a -> Bool

instance TooMany Int where
  tooMany n = n > 42

newtype Goats = Goats Int deriving (Eq, Show, TooMany)

-- the following needs FlexibleInstances pragma
instance TooMany (Int, String) where
  tooMany (n, _) = n > 33

-- or do this:
newtype AnotherTooMany = AnotherTooMany (Int, String) deriving (Eq, Show, TooMany)

instance TooMany (Int, Int) where
  tooMany (n, m) = (n + m) > 44


-- THE FOLLOWING ONES ARE NOT CORRECT !!!

instance TooMany (Num a, TooMany a) => (a, a) where
  tooMany (t1, t2) = (t1 + t2) > 44

newtype YetAnotherTooMany =
  YetAnotherTooMany (Num a, TooMany a) => (a, a)
  deriving (Eq, Show, TooMany)

Как мне изменить два последних выражения, чтобы они работали?

Я также сослался на следующие вопросы, но все еще не нашел ответа:

Добавление ограничений класса к экземпляру класса типов

Можно ли использовать ограничение класса типов вопределение нового типа?

1 Ответ

0 голосов
/ 12 октября 2018

Минимальное изменение будет следующим:

instance (Num a, Ord a, TooMany a) => TooMany (a, a) where
    tooMany (t1, t2) = (t1 + t2) > 44

Два замечания об этом экземпляре: мне пришлось добавить ограничение Ord из-за вызова (>) и ограничение TooManyизбыточен, потому что реализация не вызывает tooMany с a в качестве аргумента.Я подозреваю, что предполагаемое решение упражнения имеет немного другую реализацию метода tooMany - я призываю вас попытаться найти способ реализовать это с использованием ограничения TooMany a и без использования ограничения Ord a!

Для вашего newtype правильный синтаксис следующий:

newtype YetAnotherTooMany a = YetAnotherTooMany (a, a)
    deriving (Eq, Show, TooMany)

Вам потребуется удалить (Int, Int) экземпляр TooMany, чтобы этот точный синтаксис работал, так как в противном случае существуют перекрывающиеся экземплярывыбрать во время получения.Тем не менее, я ожидаю, что предполагаемое решение для упражнения - написать экземпляр для этого newtype самостоятельно, исходя из предположения, что экземпляр (a, a) вообще не существует - поскольку предположительно цель состоит в том, чтобы научиться использовать newtype, чтобы избежатьв первую очередь проблемы с перекрывающимися экземплярами.

...