< *>的实现对于读者

时间:2016-10-31 08:11:34

标签: haskell

有人可以解释如何运行getDogR1<$><*>都需要参数。但是Reader类型不是函数,也没有参数。那么我们如何传递Person数据类型?例如,无法使用getDogR1运行getDogR1 persgetDogR将运行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

1 个答案:

答案 0 :(得分:3)

使用runReader,例如:

runReader getDogR1 pers

Reader只是类型r -> a函数的新类型,runReader是其(唯一)字段的名称,它自动为具有相同名称的字段生成访问函数。在类型为Reader的值上使用它会提取基础函数,然后您可以像getDogR情况一样继续。