我的功能太多了:
higherOrderPure :: (a -> b) -> c
effectful :: Monad m => (a -> m b)
我想将第一个功能应用到第二个功能:
higherOrderPure `someOp` effectful :: Monad m => m c
,其中
someOp :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
示例:
curve :: (Double -> Double) -> Dia Any
curve f = fromVertices $ map p2 [(x, f x) | x <- [1..100]]
func :: Double -> Either String Double
func _ = Left "Parse error" -- in other cases this func can be a useful arithmetic computation as a Right value
someOp :: ((Double -> Double) -> Dia Any) -> (Double -> Either String Double) -> Either String (Dia Any)
someOp = ???
curve `someOp` func :: Either String (Dia Any)
答案 0 :(得分:23)
类型
Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
没有人居住,即没有具有该类型的术语t
(除非你利用分歧,例如无限递归,error
,undefined
等。)
遗憾的是,这意味着无法实现运算符someOp
。
为了证明构建这样的t
是不可能的,我们继续矛盾。
假设t
存在类型
t :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
现在,将c
专门设为(a -> b)
。我们获得了
t :: Monad m => ((a -> b) -> a -> b) -> (a -> m b) -> m (a -> b)
因此
t id :: Monad m => (a -> m b) -> m (a -> b)
然后,将monad m
专门化为延续monad (* -> r) -> r
t id :: (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
进一步将r
专门化为a
t id :: (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
所以,我们获得了
t id const :: ((a -> b) -> a) -> a
最后,通过Curry-Howard isomorphism,我们推断出以下是直觉主义的重言式:
((A -> B) -> A) -> A
但上面是众所周知的Peirce's law,这在直觉主义逻辑中是不可证明的。因此我们得到了一个矛盾。
以上证明t
不能以一般方式实施,即在任何monad中工作。在特定的monad中,这仍然是可能的。
答案 1 :(得分:5)
我认为你可以通过编写curve
的monadic版本来实现你想要的东西:
curveM :: Monad m => (Double -> m Double) -> m (QDiagram B R2 Any)
curveM f = do
let xs = [1..100]
ys <- mapM f xs
let pts = map p2 $ zip xs ys
return $ fromVertices pts
这可以很容易地写得更短,但它有你想要的类型。这类似于map -> mapM
和zipWith -> zipWithM
。函数的monadic版本必须分成不同的实现。
测试:
func1, func2 :: Double -> Either String Double
func1 x = if x < 1000 then Right x else Left "Too large"
func2 x = if x < 10 then Right x else Left "Too large"
> curveM func1
Right (_ :: QDiagram B R2 Any)
> curveM func2
Left "Too large"