我要(简单地)谈一谈耶苏德。是的,..。我也从未或真的很少使用haskell。大学lecturer.....huh。
所以我读了一本关于yesod的书,在一些章节中,作者使用了一些操作符,比如<$>和<*>。有人能用简单的话解释一下,这个操作符是做什么的?谷歌很难找到这样的图表,如果试图阅读Control.Applicative的文档,但老实说,对于一个haskell初学者来说很难找到。
因此,我希望任何人都能给我一个简单的答案:)
书中使用这些操作符的例子如下:
......
personForm :: Html -> MForm Handler (FormResult Person, Widget)
personForm = renderDivs $ Person
<$> areq textField "Name" Nothing
<*> areq (jqueryDayField def
{ jdsChangeYear = True -- give a year dropdown
, jdsYearRange = "1900:-5" -- 1900 till five years ago
}) "Birthday" Nothing
<*> aopt textField "Favorite color" Nothing
<*> areq emailField "Email address" Nothing
<*> aopt urlField "Website" Nothing
data Person = Person
{ personName :: Text
, personBirthday :: Day
, personFavoriteColor :: Maybe Text
, personEmail :: Text
, personWebsite :: Maybe Text
}
deriving Show
.......
嘿,
非常感谢,令人惊讶的是,大多数答案都是有用的。可悲的是,只有一个答案才能“解决”。非常感谢,这个教程(我在Google上真的找不到)相当不错
发布于 2013-11-07 12:02:54
如果您还没有准备好学习函子、应用程序和monads,这可能会给您一个如何使用<$>和<*>的直觉。(在我真正理解其他东西之前,我自己就通过看例子来学习如何使用它们。)如果没有<$>和<*>,代码的第一部分如下所示:
......
personForm :: Html -> MForm Handler (FormResult Person, Widget)
personForm = do
name <- areq textField "Name" Nothing
bday <- areq (jqueryDayField def
{ jdsChangeYear = True -- give a year dropdown
, jdsYearRange = "1900:-5" -- 1900 till five years ago
}) "Birthday" Nothing
colour <- aopt textField "Favorite color" Nothing
email <- areq emailField "Email address" Nothing
url <- aopt urlField "Website" Nothing
renderDivs $ Person name bday colour email url换句话说,<$>和<*>可以消除创建许多我们只使用一次的符号的需要。
发布于 2013-11-07 11:54:41
我总是非常小心的时候,作出的答案,主要是由链接,但this is one amazing tutorial解释函子,应用程序,并给予一些理解的单一。
发布于 2013-11-07 13:31:49
当然,最简单的答案是类型。这些运算符来自类型类型Functor及其子类Applicative。
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
(<$>) = fmap -- synonym
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b最简单的直观答案是,Functors和Applicative允许您用“元数据”注释简单值,(<$>)、(<*>)和朋友允许您转换“常规”值级函数来处理“注释”值。
go x y -- works if x and y are regular values
go <$> pure x <*> pure y -- uses `pure` to add "default" metadata
-- but is otherwise identical to the last one不过,就像任何简单的答案一样,这是个谎言。“元数据”是一个非常简化的术语。更好的是“计算上下文”或“效果上下文”或“容器”。
如果您熟悉Monad,那么您已经非常熟悉这个概念了。所有的Monad都是Applicative的,所以您可以认为(<$>)和(<*>)为一些do表示法提供了另一种语法。
do x_val <- x go <$> x
y_val <- y <*> y
return (go x_val y_val)它有较少的符号,并强调对两个参数“应用”go的概念,而不是强调“获取x生成的值,然后得到y生成的值,然后将这些值应用于go,然后像do语法那样重新包装结果”的概念。
我可以抛出的最后一个直觉是,以一种完全不同的方式来看待Applicative。Applicative等价于另一个名为Monoidal的类。
class Functor f => Monoidal f where
init :: f () -- similar to pure
prod :: f a -> f b -> f (a, b) -- similar to (<*>)以便Monoidal Functor允许您(a)用一个平凡的值实例化它们。
init :: [()]
init = []
init :: Maybe ()
init = Just ()还把其中的两个人挤在一起生产他们的产品
prod :: [a] -> [b] -> [(a, b)]
prod as bs = [(a, b) | a <- as, b <- bs]
prod :: Maybe a -> Maybe b -> Maybe (a, b)
prod (Just a) (Just b) = (Just (a, b))
prod _ _ = Nothing这意味着,使用Monoidal函子,您可以将大量的值粉碎在一起,然后在整个簇上创建一个值级函数fmap。
go <$> maybeInt `prod` (maybeChar `prod` maybeBool) where
go :: (Int, (Char, Bool)) -> Double -- it's pure!
go (i, (c, b)) = ...这在本质上就是你对(<$>)和(<*>)所做的,只是用更少的元组
go <$> maybeInt <*> maybeChar <*> maybeBool where
go :: Int -> Char -> Bool -> Double
go i c b = ...最后,下面是两个概念之间的转换方式
-- forward
init = pure ()
prod x y = (,) <$> x <*> y
-- back
pure a = const a <$> init
f <*> x = ($) <$> prod f x这说明了如何将(<*>)视为采用正常值级应用程序($)并将其注入Functor内部的product中。
https://stackoverflow.com/questions/19834982
复制相似问题