Как я могу сделать (a, a)
a Functor
, не прибегая к newtype
?
В основном я хочу, чтобы он работал следующим образом:
instance Functor (a, a) where
fmap f (x, y) = (f x, f y)
Но, конечно, это не законный способ выразить это:
Kind mis-match
The first argument of `Functor' should have kind `* -> *',
but `(a, a)' has kind `*'
In the instance declaration for `Functor (a, a)'
То, что я действительно хочу, это функция типа типа: \a -> (a, a)
(недопустимый синтаксис). Таким образом, псевдоним типа, возможно?
type V2 a = (a, a)
instance Functor V2 where
fmap f (x, y) = (f x, f y)
Я бы подумал, что это сработает, но это не так. Сначала я получаю эту жалобу:
Illegal instance declaration for `Functor V2'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Functor V2'
Если я следую советам и добавлю расширение TypeSynonymInstances
, я получаю новую ошибку:
Type synonym `V2' should have 1 argument, but has been given 0
In the instance declaration for `Functor V2'
Хорошо, дух, это точка! V2
имеет вид * -> *
, который требуется от экземпляра Functor
. Хорошо, хорошо, я могу использовать newtype
следующим образом:
newtype V2 a = V2 (a, a)
instance Functor V2 where
fmap f (V2 (x, y)) = V2 (f x, f y)
Но теперь мне нужно посыпать V2
либерально по всему моему коду, вместо того, чтобы просто иметь дело с простыми кортежами, что поражает мысль сделать его Functor
; в этот момент я мог бы также создать свою собственную функцию vmap :: (a -> b) -> (a, a) -> (b, b)
.
Итак, есть ли способ сделать это красиво, т.е. без newtype
?