有人可以解释如何运行getDogR1
。 <$>
和<*>
都需要参数。但是Reader
类型不是函数,也没有参数。那么我们如何传递Person
数据类型?例如,无法使用getDogR1
运行getDogR1 pers
,getDogR
将运行getDogR pers
。
newtype Reader r a = Reader {runReader :: r -> a}
instance Functor (Reader r) where
fmap f (Reader f1) = Reader $ f . f1
instance Applicative (Reader r) where
pure :: a -> Reader r a
pure a = Reader $ const a
(<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b
Reader rab <*> Reader ra = Reader $ \r -> rab r (ra r)
-----------------------------------------------------------------
newtype HumanName = HumanName String deriving (Eq, Show)
newtype DogName = DogName String deriving (Eq, Show)
newtype Address = Address String deriving (Eq, Show)
data Person = Person {
humanName :: HumanName
, dogName :: DogName
, address :: Address
} deriving (Eq, Show)
data Dog = Dog {
dogsName :: DogName
, dogsAddress :: Address
} deriving (Eq, Show)
pers :: Person
pers = Person (HumanName "Big Bird")
(DogName "Barkley")
(Address "Sesame Street")
dDuck :: Person
dDuck = Person (HumanName "Jeff")
(DogName "Mutley")
(Address "Some Street")
getDog :: Person -> Dog
getDog p = Dog (dogName p) (address p)
getDogR :: Person -> Dog
getDogR = Dog <$> dogName <*> address
getDogR' :: Person -> Dog
getDogR' = liftA2 Dog dogName address
getDogR1 :: Reader Person Dog
getDogR1 = Dog <$> Reader dogName <*> Reader address
答案 0 :(得分:3)
使用runReader
,例如:
runReader getDogR1 pers
Reader
只是类型r -> a
函数的新类型,runReader
是其(唯一)字段的名称,它自动为具有相同名称的字段生成访问函数。在类型为Reader
的值上使用它会提取基础函数,然后您可以像getDogR
情况一样继续。