【发布时间】:2017-07-05 15:49:18
【问题描述】:
我在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,但如果我注释掉begin 和end 函数调用和定义,那么haskell 就不再知道如何处理values。我想这是因为他们定义中的相等性测试是让 haskell 推断类型的原因(我错了吗?)。
- 在那种情况下,是的动作到底是什么?
- 还有
values如何知道将permutations应用于哪个有界类型?这部分似乎很神秘。 - 最后,如果我想保持不变
代码如上,但修改它列出所有排列(不仅仅是
满足
begin和end) 我该怎么做?
【问题讨论】:
-
从技术上讲,它不是运算符;它只是将
>>=运算符的结果绑定到隐式函数中的名称的语法。a <- b被解析为b >>= (\a -> ...),其中...是do块的其余部分。 -
如果没有
begin和end(它们的相等性测试确实可以指导类型推断,因为只有与==相同的东西才能被测试),类型检查器没有办法看到你在谈论Nations 和Colors。它只是看到你想要Bounded、Enum和Show这两种类型,并且非常正确地拒绝猜测你的意思。 -
哦该死的列表 Monad。是的,这并不是最直接的例子。
-
列表理解会更符合这一点。这种风格可能用于模仿逻辑编程,但它本身并不是一种很好的风格(IMO)。 (我也发现
do..where很糟糕的风格)
标签: haskell