无法理解fp-course的Haskell练习

c9qzyr3d  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(174)

我不能理解fp-course中的一个练习题的答案。
https://github.com/system-f/fp-course/blob/7a957a177ccdc9d91323c32d576351dcc1234f2f/src/Course/Monad.hs#L119

-- | Flattens a combined structure to a single structure.
--
-- >>> join ((1 :. 2 :. 3 :. Nil) :. (1 :. 2 :. Nil) :. Nil)
-- [1,2,3,1,2]
--
-- >>> join (Full Empty)
-- Empty
--
-- >>> join (Full (Full 7))
-- Full 7
--
-- >>> join (+) 7
-- 14
join ::
  Monad k =>
  k (k a)
  -> k a
join x = id =<< x

id :: a -> a(=<<) :: (a -> k b) -> k a -> k b
为什么id可以是(=<<)的第一个参数?
为什么答案是join x = id =<< x

xqk2d5yq

xqk2d5yq1#

为什么id可以是(=<<)的第一个参数?
也许在类型必须相等的地方将类型一对一地排列会有帮助。这对应于编译器在类型检查期间所做的 * 统一
| ↓术语|类型→|||||||||||
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|
| (=<<)|- -|(|a1|→|k**B|)|→|k|a1|→|k**B|
| id|- -||a2|→|a2|||||||
| (=<<) id|- -|||||||k|a1|→|k**B|
| | | | ↑|||||k|a2|→|k**B|
| | | | | | ↑|||k|(*kB
|→|*kB*|
注意,有两个不同类型的变量名为a。在GHCi中,您可以设置:set -fprint-explicit-foralls,然后:type id将显示forall a. a -> a。这显示了参数a的局部作用域,就像\x -> …定义x的作用域一样。
为什么答案是join x = id =<< x
(=<<)是mapping(fmap/(<$>))和flattening(join)的组合,即f =<< x = join (fmap f x)。由于join仅为flattening,因此我们可以通过将“mapping”部分设置为id,使用(=<<)表示join
为什么id =<< (Full 8)不能变成8
id =<< Full (Full 8)意味着我们将idMap到所有元素fmap id (Full (Full 8)) = Full (id (Full 8)) = Full (Full 8)上,然后将Optional (Optional t1)平坦化为Optional t1,对于某种类型t1,其中8 :: (Num t1) => t1
如果我们尝试id =<< Full 8,那么我们可以Mapfmap id (Full 8) = Full (id 8) = Full 8,但我们只有Optional t1。这不是错误,但它增加了一个约束:对于某种类型t2t1必须等于Optional t2。该等式约束的语法是t1 ~ Optional t2。但是没有任何类型可以工作,除非您为Num (Optional t2)添加一个示例。(这在技术上是可行的,但不是标准的。)

相关问题