理解Haskell(&lt ;-)运算符

时间:2017-07-05 15:49:19

标签: haskell

我正在https://rosettacode.org/wiki/Zebra_puzzle#LP-like_version研究代码并且有些困惑。

以下是该代码中发生的事情的最小示例。

import Control.Monad
import Data.List

values :: (Bounded a, Enum a) => [[a]]
values = permutations [minBound..maxBound]

data Nation = English | Swede | Dane
  deriving (Bounded, Eq, Enum, Show)

data Color = Red | Blue | Green
  deriving (Bounded, Eq, Enum, Show)

answers = do

  nation <- values
  begin nation English

  color <- values
  end color Red

  return $ zip nation color

  where
    end xs x = guard $ last xs == x
    begin xs x = guard $ head xs == x

main :: IO ()
main = do
    forM_ answers $ (\answer ->  -- for answer in answers:
      do
        mapM_ print answer
        putStrLn "----" )
    putStrLn "No more solutions!"

对我来说,神秘的是do块中发生的事情。

我从各种渠道了解到a <- b运算符执行了一个操作b并将其绑定到a。但这里的行动到底是什么?

我认为它是values,但如果我注释掉beginend函数调用和定义,那么haskell就不知道如何处理values了。我想这是因为他们定义中的相等测试是让haskell推断出类型的原因(我错了吗?)。

  1. 在这种情况下,
  2. values如何知道将permutations应用于哪个有界类型?这部分看起来很神秘。
  3. 最后,如果我想保持不变 代码如上,但修改它列出所有排列(不仅仅是 一个满足beginend)我将如何做到这一点?

1 个答案:

答案 0 :(得分:0)

您可以将do表示法翻译成列表理解符号:

answers = [ zip nation color
          | nation <- values, head nation == English
          , color <- values, last color == Red
          ]

我真的不喜欢这个headlast业务。