Bra*_*FRZ 2 haskell pattern-matching higher-order-functions higher-order-types
我知道在Haskell中模式匹配函数是不可能的,我完全理解为什么.但是,我有两个密切相关的问题.首先,如果您想部分应用函数以供以后使用,是否有一种方法可以定义和捕获返回值(如果它是一个元组)?或者我错了,这还在尝试模仿我鼻子下的匹配功能?
例如,假设我正在尝试获取具有10的不同倍数的值的商和余数.然后,我怎么写这样的东西?
q, r :: Integral a => a -> a
(q, r) = (12345 `quotRem`)
Run Code Online (Sandbox Code Playgroud)
我在这里意识到,存在单独的功能,所以我可以这样做:
q, r :: Integral a => a -> a
q = (12345 `quot`)
r = (12345 `rem`)
Run Code Online (Sandbox Code Playgroud)
但是,这是一个非常具体的案例,并且有无限的其他函数示例返回元组,这些函数可以很好地概括.例如,一个返回列表中的平均数和赔率的函数.
evens, odds :: Integral a => [a] -> Int
(evens, odds) = (length . (filter even), length . (filter odd))
Run Code Online (Sandbox Code Playgroud)
这引出了我的第二个问题.以上在GHCi中工作得很好.
Prelude> let (evens, odds) = (length . (filter even), length . (filter odd))
Prelude> :t evens
evens :: Integral a => [a] -> Int
Prelude> evens [1..10]
5
Run Code Online (Sandbox Code Playgroud)
甚至更令人困惑的是它甚至可以通过"模式匹配"工作,就像我(q, r)在开始时玩的一样:
Prelude> let evensOdds = (length . (filter even), length . (filter odd))
Prelude> :t evensOdds
evensOdds :: (Integral a1, Integral a) => ([a1] -> Int, [a] -> Int)
Prelude> let (ev,od) = evensOdds
Prelude> :t ev
ev :: Integral a1 => [a1] -> Int
Prelude> ev [1..10]
5
Run Code Online (Sandbox Code Playgroud)
它也适用于加载到GHCi中的实际文件,即使(evens, odds)没有.为什么这两个不同,为什么第二个在GHCi中工作,如果它不能正常工作?可以通过某种方式利用这里的不同之处吗?
你永远不会在一个函数上模式匹配.您始终在pair-constructor上进行模式匹配(,).你的(even, odds)榜样
(evens, odds) = (length . (filter even), length . (filter odd))
Run Code Online (Sandbox Code Playgroud)
就像工作一样
(first, second) = (x, y)
Run Code Online (Sandbox Code Playgroud)
在那一点上,什么类型x并没有关系y.
(q, r)由于quotRem类型的原因,您的示例无效.让我们回顾一下,并将其与(q, r)类型进行比较:
quotRem :: Integral n => n -> n -> (n , n)
quotRem 12345 :: Integral n => n -> (n , n)
(q, r) :: Integral n => (n -> n, n -> n)
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,这对(q, r)'的类型不同于quotRem一个.仍然可以编写你的函数:
pairify :: (a -> (b, c)) -> (a -> b, a -> c)
pairify f = (fst . f, snd . f)
(q,r) = pairify (quotRem 12345)
Run Code Online (Sandbox Code Playgroud)
但正如你所看到的,我们并没有从中获得太多pairify.顺便说一下,partitionfrom Data.List提供你的(even, odds)功能:
(even, odds) = pairify (partition even)
Run Code Online (Sandbox Code Playgroud)