haskell idris支持将对称语句压缩成一个语句的方法吗?

uelo1irk  于 9个月前  发布在  其他
关注(0)|答案(3)|浏览(50)

我是函数式编程的新手,所以通过“使用Idris进行类型驱动开发”来工作。给予一个函数maxMaybe,它可以计算两个Maybe Double之间的最大值,定义如下

maxMaybe : Ord a => Maybe a -> Maybe a -> Maybe a
maxMaybe Nothing y = y
maxMaybe x Nothing = x
maxMaybe Nothing Nothing = Nothing
maxMaybe (Just x) (Just y) = Just (max x y)

有没有一种方法可以将下面的情况分解成一个,因为位置并不重要?

maxMaybe Nothing y = y
maxMaybe x Nothing = x

我也很想知道这种事情是否在其他纯函数式编程语言(如Haskell或OCaml)中普遍处理

maxMaybe : Ord a => Maybe a -> Maybe a -> Maybe a
maxMaybe Nothing y = y
-- maxMaybe x Nothing = x
maxMaybe Nothing Nothing = Nothing
maxMaybe (Just x) (Just y) = Just (max x y)

maxMaybe(Just 5)(Nothing)maxMaybe(Just 5)Nothing:也许是

w80xi6nr

w80xi6nr1#

你可以写

maxMaybe : Ord a => Maybe a -> Maybe a -> Maybe a
maxMaybe mx my = [| max mx my |] <|> mx <|> my

但是在运行时它的开销可能会更大,因为你需要重做大量的案例分析,除非有足够的编译器优化来给予与原始解决方案基本等价的东西。

ua4mk5z4

ua4mk5z42#

您已经在Haskell和OCaml中询问了两个答案,到目前为止只提供了Haskell中的答案。因此,我将给予OCaml的等价物,而不重复Haskell代码。
由于这个问题是关于合并match语句的对称分支,下面是你的版本如何用OCaml编写的:

let max_option x y = match x, y with
  | None, y -> y
  | x, None -> x
  | None, None -> None
  | Some x, Some y -> Some (max x y)

这是折叠后的版本

let max_option x y = match x, y with
  | None, v | v, None -> v (* two branches are merged *)
  | Some x, Some y -> Some (max x y)
  (* the `None, None` branch has been deleted as it was redundant *)

但是,对于这个特定的情况,由于'a option(Haskell中的Maybe a)是一个monad,使用monadic let绑定会更习惯:

let max_option x y =
  let (let>) = Option.bind in
  let> x = x in
  let> y = y in
  Some (max x y)

因为这个例子有点做作,所以你会得到一些奇怪的let> x = x语句。你可能会使用更多的高级函数,但我不认为这会产生更符合OCaml语言习惯的代码,这与Haskell相反。

r8xiu3jd

r8xiu3jd3#

在Haskell中,一个想法可能是使用Min半群并使用以下内容进行 Package :

import Data.Function (on)
import Data.Semigroup (Max (Max, getMax))

maxMaybe :: Ord a => Maybe a -> Maybe a -> Maybe a
maxMaybe = on ((fmap getMax .) . (<>)) (fmap Max)

你可以很容易地将其推广到任何类似Semigroup的结构:

semiFunc :: (Functor f, Semigroup (f b)) => (a -> b) -> (b -> c) -> f a -> f a -> f c
semiFunc f g = on ((fmap g .) . (<>)) (fmap f)

maxMaybesemiFunc的特殊情况,其中maxMaybe = semiFunc Max getMax

相关问题