我也有功能:
higherOrderPure :: (a -> b) -> c
effectful :: Monad m => (a -> m b)
Run Code Online (Sandbox Code Playgroud)
我想将第一个函数应用于第二个函数:
higherOrderPure `someOp` effectful :: Monad m => m c
Run Code Online (Sandbox Code Playgroud)
哪里
someOp :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Run Code Online (Sandbox Code Playgroud)
例:
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)
Run Code Online (Sandbox Code Playgroud)
chi*_*chi 23
类型
Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Run Code Online (Sandbox Code Playgroud)
没有人居住,即不存在长期t
具有类型(除非你利用的分歧,比如无限递归error
,undefined
等等).
遗憾的是,这意味着不可能实现操作员someOp
.
为了证明构建这样的a是不可能的t
,我们继续矛盾.假设t
存在类型
t :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Run Code Online (Sandbox Code Playgroud)
现在,专门c
到(a -> b)
.我们获得
t :: Monad m => ((a -> b) -> a -> b) -> (a -> m b) -> m (a -> b)
Run Code Online (Sandbox Code Playgroud)
于是
t id :: Monad m => (a -> m b) -> m (a -> b)
Run Code Online (Sandbox Code Playgroud)
然后,将monad专门化为m
continuation monad(* -> r) -> r
t id :: (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
Run Code Online (Sandbox Code Playgroud)
进一步专注r
于a
t id :: (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
Run Code Online (Sandbox Code Playgroud)
所以,我们获得了
t id const :: ((a -> b) -> a) -> a
Run Code Online (Sandbox Code Playgroud)
最后,通过库里 - 霍华德的同构,我们推断出以下是直觉主义的同义反复:
((A -> B) -> A) -> A
Run Code Online (Sandbox Code Playgroud)
但上面是众所周知的皮尔士定律,这在直觉逻辑中是不可证明的.因此,我们获得了矛盾.
以上证明t
不能以一般方式实施,即在任何单子中工作.在特定的monad中,这仍然是可能的.
我认为你可以通过编写一个monadic版本来实现你想要的curve
:
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
Run Code Online (Sandbox Code Playgroud)
这可以很容易地写得更短,但它有你想要的类型.这类似于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"
Run Code Online (Sandbox Code Playgroud)