Я пытался выяснить более тонкие части системы типов Haskell, написав библиотеку Vector. В идеале мне бы хотелось иметь перегруженную операцию умножения векторов, которая работает немного как C++, т. е. вы можете умножать вектор любого размера на скаляр в любом порядке. Я попытался объединить несколько классов типов параметров и расширение семейств типов, чтобы сделать это:
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}
data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)
class Vector a where
(<+>) :: a -> a -> a
class VectorMul a b where
type Result a b
(<*>) :: a -> b -> Result a b
instance (Num a) => Vector (Vec2 a) where
Vec2 (x1,y1) <+> Vec2 (x2,y2) = Vec2 (x1+x2, y1+y2)
instance (Num a) => VectorMul (Vec2 a) a where
type Result (Vec2 a) a = (Vec2 a)
Vec2 (x,y) <*> a = Vec2 (x*a, y*a)
works :: (Num a) => Vec2 a -> a -> Vec2 a
works a b = a <*> b
Этот код работает, по крайней мере, при использовании функции works
. Но когда я пытаюсь ввести простое выражение, такое как Vec2 (3,4) <*> 5
, в GHCi, он сообщает, что переменные типа (Num xx)
неоднозначны. Это странно для меня... что я упускаю в этом случае? Haskell должен иметь возможность выбирать один и тот же произвольный тип для литералов, чтобы выражение типа работало (как это происходит в функции works
).
works
вы явно говоритеa
вVec2 a
, а второй аргументa
имеет тот же тип. - person Satvik   schedule 18.08.2013