haskell - 如何让 Haskell 计算正确的多态类型?

标签 haskell functional-programming types polymorphism

我才意识到这个小小的 on 是多么有用功能可以。

前任:

orderByLength = sortBy (compare `on` length) 

但不幸的是,推断的类型可能有点违反直觉。

根据定义
f `on` g = \x y -> f (g x) (g y)

一个可以例如代替
(==) `on` length


\x y -> (length x) == (length y)

但两者都有不同的类型!

第一个有[a] -> [a] -> Bool而第二个具有正确的、更通用的 [a] -> [b] -> Bool 类型.

这不允许明显正确的术语,如 (on (==) length) [1, 2, 3] ["a", "b", "c"] (应该会产生 True 但现在甚至无法通过类型检查)。

我知道这个限制是由于使用了first-rank types ,但是如何克服呢?有人可以制定on 的实现吗?可以正确处理多态函数(使用通用量化/rank-n 类型)?

最佳答案

{-# LANGUAGE Rank2Types #-}
on' :: (a -> a -> b) -> (forall d. c d -> a) -> c e -> c f -> b
on' f g x y = f (g x) (g y)

这导致
Prelude> :t on' (==)
on' (==) :: (Eq a) => (forall d. c d -> a) -> c e -> c f -> Bool
Prelude> :t on' (==) length
on' (==) length :: [e] -> [f] -> Bool

On the other hand, this signature also makes flip on' id illegal, which is somewhat less than desirable.


{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
onE f g = do
    x <- newName "x"
    y <- newName "y"
    lamE [varP x, varP y] $ f `appE` (g `appE` varE x) `appE` (g `appE` varE y)

前奏> :set -XTemplateHaskell
前奏> $(onE [|(==)|] [|length|]) [1,2,3] ["a","b","c"]
真的
前奏> $(onE [|(==)|] [|id|]) 4 5
错误的

关于haskell - 如何让 Haskell 计算正确的多态类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1828652/

相关文章:

Haskell dmenu 在按键时自动启动

haskell - 有人可以向我解释为什么ArrowApply的应用程序功能使它们像monad一样强大吗?

algorithm - 优雅的 Array.multipick(?) 实现

node.js - Node - 意外标识符

haskell - 使用自己的数据类型和映射求解逻辑公式

python - 在Scikit中测试DecisionTreeClassifier时出错,请使用Python学习

c# - 如何在此示例方法中使用 (Switch) 而不是 (IF & Else)

haskell - let 语句中的 case 语句需要什么缩进?

haskell - 为什么包装 Data.Binary.Put monad 会导致内存泄漏? (第2部分)

Swift [1,2] 符合 AnyObject 但 [Enum.a, Enum.b] 不符合