7

假设我们有一个类似 f 的函数,它返回一个 monad。然而,在你看到的地方Int,假装它是一个非常复杂的类型。

f :: (Monad m) => m Int -- Pretend this isn't Int but something complicated
f = return 42

现在让我们说我们想强制它进入Maybemonad。我们不需要编写完整的类型f来执行此操作,我们可以执行以下操作:

g :: Maybe a -> Maybe a
g = id

main = print $ (g f)

哑函数g强制f变为Maybe

我认为上面的内容相当混乱。我宁愿写的是这样的:

main = print $ (f :: Maybe a)

但它失败并出现以下错误:

Couldn't match expected type `a' against inferred type `Int'
  `a' is a rigid type variable bound by
      the polymorphic type `forall a. Maybe a' at prog.hs:7:16
  Expected type: Maybe a
  Inferred type: Maybe Int
In the second argument of `($)', namely `(f :: Maybe a)'
In the expression: print $ (f :: Maybe a)

有没有办法以g不涉及创建新功能的不那么混乱的方式完成上述工作?我不想写f :: Maybe Int,因为如果返回类型发生变化,它就会成为维护问题。GHC 扩展在答案中是可以的。

4

2 回答 2

10

使用asTypeOf. 它返回第一个参数,同时将其类型与第二个参数统一。它只是 的类型限制版本const,但在这种情况下很有用。

main = print $ f `asTypeOf` (undefined :: Maybe a)
于 2012-08-01T01:38:19.160 回答
8

另一种方法是限制 的类型print

main = (print :: Show a => Maybe a -> IO ()) f

更新:
GHC 8.0.1 引入了TypeApplications扩展,可用于强制Maybe

{-# LANGUAGE TypeApplications #-}

main = print $ f @Maybe
于 2012-08-01T05:40:06.587 回答