Это зависит от того, что вы пытаетесь сохранить в A
.
Если вы пытаетесь сохранить любую подобную функцию, пока m
является Monad
, используйте ее как параметр типа и укажите это ограничение в своих функциях:
newtype A m = A { _run :: A m -> [Int] -> m Int }
myFunction :: Monad m => A m -> A m
Затем вы можете иметь такие вещи, как A [] -> [Int] -> [Int]
или A Maybe -> [Int] -> Maybe Int
внутри конструктора.
f :: A Maybe -> [Int] -> Maybe Int
f _ (x:_) = Just x
f _ [] = Nothing
g :: Monad m => A m -> [Int] -> m Int
g _ xs = return $ head xs
myA :: A Maybe
myA = A f -- this works
myOtherA :: Monad m => A m
myOtherA = A g -- this works too
С другой стороны, если вы хотите, чтобы данные, которые вы храните, были полиморфными, вы можете использовать расширение GHC RankNTypes
.
{-# LANGUAGE RankNTypes #-}
newtype A = A { _run :: forall m. Monad m => A -> [Int] -> m Int }
myFunction :: A -> A
В конструкторе не может быть таких вещей, как A -> [Int] -> [Int]
или A -> [Int] -> Maybe Int
, потому что forall
заставляет их быть общими по отношению к любому Monad m
, поэтому он должен иметь тип Monad m => A -> [Int] -> Maybe Int
.
f :: A -> [Int] -> Maybe Int
f _ (x:_) = Just x
f _ [] = Nothing
g :: Monad m => A -> [Int] -> m Int
g _ xs = return $ head xs
myA :: A
myA = A f -- this does not work ; it wants forall m. Monad m => m, not []
myOtherA :: A
myOtherA = A g -- this does work
Это будет действительно полезно, только если вы собираетесь использовать разные конкретные экземпляры Monad
для A
-значения. Например, линзы работают таким образом, используя разные функторы для разных действий с линзой.
person
zbw
schedule
17.04.2017
newtype A = A { _run :: A -> [Int] -> (forall m. Monad m => m Int) }
(требуется расширение{-# LANGUAGE RankNTypes #-}
). - person ZhekaKozlov   schedule 17.04.2017