Haskell语法:{..}和@的含义

时间:2013-09-24 10:32:20

标签: haskell yesod

我只是在学习Yesod / Haskell。

在下面的代码(http://www.yesodweb.com/book/restful-content)中有两件我不理解的事情(以及随后的问题)。

  1. {..} - 这是什么意思? (对谷歌而言,这是一个艰难的术语。)
  2. person@Person - @签到了什么?
  3. 有没有办法可以找到不可编辑的Haskell语法的答案,而无需在StackOverflow上烦你所有人?
  4. 代码:

    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE QuasiQuotes       #-}
    {-# LANGUAGE RecordWildCards   #-}
    {-# LANGUAGE TemplateHaskell   #-}
    {-# LANGUAGE TypeFamilies      #-}
    import           Data.Text (Text)
    import           Yesod
    
    data Person = Person
        { name :: Text
        , age  :: Int
        }
    
    instance ToJSON Person where
        toJSON Person {..} = object
            [ "name" .= name
            , "age"  .= age
            ]
    
    data App = App
    
    mkYesod "App" [parseRoutes|
    / HomeR GET
    |]
    
    instance Yesod App
    
    getHomeR :: Handler TypedContent
    getHomeR = selectRep $ do
        provideRep $ return
            [shamlet|
                <p>Hello, my name is #{name} and I am #{age} years old.
            |]
        provideJson person
      where
        person@Person {..} = Person "Michael" 28
    
    main :: IO ()
    main = warp 3000 App
    

3 个答案:

答案 0 :(得分:13)

对于第1点和第2点,我猜你是指行

person@Person {..}

{..}来自RecordWildcards扩展程序。基本上它会为Person数据类型的所有字段带来范围。这就是为什么你可以在上面的哈姆雷特模板中使用nameage

@用作别名。每当您看到id@deconstructor_expr时,您都可以使用id获取由deconstructor_expr解构的整个值。例如,您可以拥有

f (x:a@(y:_)) = a

a将是参数列表的tail,只要该列表至少有2个元素(ftail,对于超过2个元素)。

如果没有这两个,整个功能必须改为

getHomeR :: Handler TypedContent
getHomeR = selectRep $ do
    provideRep $ return
        [shamlet|
            <p>Hello, my name is #{name'} and I am #{age'} years old.
        |]
    provideJson person
  where
    person = Person "Michael" 28
    name' = name person
    age' = age person

观察nameage是从记录到特定字段的函数,这意味着您必须使用其他名称作为值(' - 结束变量)。另外,由于我们不再使用@,因此person和字段需要单独的行。

另一种选择是

getHomeR :: Handler TypedContent
getHomeR = selectRep $ do
    provideRep $ return
        [shamlet|
            <p>Hello, my name is #{name person} and I am #{age person} years old.
        |]
    provideJson person
  where
    person = Person "Michael" 28

您仍然需要调用nameage函数。

对于第3点,有可能在#haskell上进行IRC并在那里问问。无论如何,来自那里的人都在这里,问起来并不是很麻烦。

答案 1 :(得分:7)

添加其他答案,搜索不可插入的语法时使用symbolhound.com

答案 2 :(得分:2)

{..}将记录解压缩到变量中。在您的情况下,它定义nameage@在模式匹配中获取整个值,因此在person@Person {..}中,person将是原始Person值。