2016-05-26 9 views
3

Haskell книга хочет, чтобы реализовать проходимый экземпляр дляTraversable данных константы а б = константа а проходит Quickchecks, но действует смешно

newtype Constant a b = Constant { getConstant :: a } 

включая весь необходимый суперкласс. Приведенный ниже код передает Quickcheck/Checkers, но действует смешно

import Test.QuickCheck 
import Test.QuickCheck.Checkers 
import Test.QuickCheck.Classes 

newtype Constant a b = Constant { getConstant :: a } 

instance Functor (Constant a) where 
    fmap f (Constant a) = Constant a 

instance Foldable (Constant a) where 
    foldr f z (Constant x) = z 

instance Traversable (Constant a) where 
    traverse f (Constant a) = pure $ Constant a  

type TI = [] 
main = do 
    let trigger = undefined :: TI (Int, Int, [Int]) 
    quickBatch (traversable trigger) 

Когда я пытаюсь использовать проходимую экземпляр вроде так:

traverse (\x -> [x + 1]) $ Constant 5 

Я не получаю Constant [5] который я надеялся, а

traverse (\x -> [x + 1]) $ Constant 5 
    :: (Num b, Num a) => [Constant a b] 

Что это значит? Я сделал что-то не так?

+3

A Haskell koan: 'Constant 5' не содержит константу' 5'. –

ответ

5

Когда я пытаюсь использовать проходимую экземпляр вроде так:

traverse (\x -> [x + 1]) $ Constant 5 

Я не получаю Constant [5] который я надеялся на [...]

Вы не собираетесь для получения Constant [5]. Напишем типа для traverse:

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) 

... и линия его с конкретизацией его:

    -- I've substituted `x` for `a` and `y` for `b` in the 
        -- first type, because otherwise my head hurts. 
        (x -> f y) -> t   x -> f (t   y) 
(Num a, Num b) => (a -> [] a) -> (Constant b) a -> [] ((Constant b) a) 

Таким образом, мы имеем:

t = Constant b 
f = [] 
x = Num a => a 
y = NUm b => b 

Обратите внимание, что тип для traverse подразумевает, что t будет таким же в аргументе и результате. Поскольку вы используете Constant 5 :: Num a => Constant a b в качестве аргумента, это означает, что в результате вы никогда не сможете получить Constant [5] :: Num a => Constant [a] b, потому что Constant a /= Constant [a].

+0

Спасибо, подумаю об этом. Является ли моя реализация правильной? –

+0

Тем не менее, он не возвращает 'Constant 5' или ничего конкретного, он просто возвращает тип с ограничением или чем-то похожим ... –

+3

@ TheUnfunCat: Ваша реализация выглядит правильно. Одно упражнение, которое вы могли бы оценить, это следующее: как бы вы могли написать другой экземпляр «Traversable» для 'Constant'? (Подсказка: это трюк!) В любом случае, ваш пример должен оценивать значение '[Constant 5]'; вы должны иметь возможность сопоставить шаблон с результатом, чтобы убедиться в этом. Это точка функтора 'Constant' - это предельный случай для' Functor'/'Applicative' /' Traversable', который просто игнорирует функции, которые вы накладываете на него. –

 Смежные вопросы

  • Нет связанных вопросов^_^