gpt4 book ai didi

haskell - Haskell 中的换能器和单态性限制

转载 作者:行者123 更新时间:2023-12-04 15:10:56 26 4
gpt4 key购买 nike

我在 Haskell 中实现了如下的转换器:

{-# LANGUAGE RankNTypes #-}

import Prelude hiding (foldr)
import Data.Foldable

type Reducer b a = a -> b -> b
type Transducer a b = forall t. Reducer t b -> Reducer t a

class Foldable c => Collection c where
insert :: a -> c a -> c a
empty :: c a

reduce :: Collection c => Transducer a b -> c a -> c b
reduce f = foldr (f insert) empty

mapping :: (a -> b) -> Transducer a b
mapping f g x = g (f x)

现在我想定义一个通用的 map功能。因此,我将上述代码加载到 GHCi 中:

Prelude> :load Transducer
[1 of 1] Compiling Main ( Transducer.hs, interpreted )
Ok, modules loaded: Main.
*Main> let map = reduce . mapping

<interactive>:3:20:
Couldn't match type ‘Reducer t0 b1 -> Reducer t0 a1’
with ‘forall t. Reducer t b -> Reducer t a’
Expected type: (a1 -> b1) -> Transducer a b
Actual type: (a1 -> b1) -> Reducer t0 b1 -> Reducer t0 a1
Relevant bindings include
map :: (a1 -> b1) -> c a -> c b (bound at <interactive>:3:5)
In the second argument of ‘(.)’, namely ‘mapping’
In the expression: reduce . mapping
*Main> let map f = reduce (mapping f)
*Main> :t map
map :: Collection c => (a -> b) -> c a -> c b

所以我无法定义 map = reduce . mapping .但是,我可以定义 map f = reduce (mapping f) .

我相信这个问题是由单态限制引起的。我真的很想写 map = reduce . mapping而不是 map f = reduce (mapping f) .因此,我有两个问题:
  • 是什么导致了这个问题?确实是单态限制吗?
  • 我该如何解决这个问题?
  • 最佳答案

    如果您制作 Transducer一个 newtype ,比 GHC 计算出的类型要好得多。存在类型变量不会逃脱范围 - 转换器将保持多态性。

    换句话说,具有以下定义 map = reduce . mapping作品

    {-# LANGUAGE RankNTypes #-}

    import Prelude hiding (foldr, map, (.), id)
    import Control.Category
    import Data.Foldable

    type Reducer b a = a -> b -> b
    newtype Transducer a b = MkTrans { unTrans :: forall t. Reducer t b -> Reducer t a }

    class Foldable c => Collection c where
    insert :: a -> c a -> c a
    empty :: c a

    instance Collection [] where
    insert = (:)
    empty = []

    reduce :: Collection c => Transducer a b -> c a -> c b
    reduce f = foldr (unTrans f insert) empty

    mapping :: (a -> b) -> Transducer a b
    mapping f = MkTrans $ \g x -> g (f x)

    filtering :: (a -> Bool) -> Transducer a a
    filtering f = MkTrans $ \g x y -> if f x then g x y else y

    map :: Collection c => (a -> b) -> c a -> c b
    map = reduce . mapping

    filter :: Collection c => (a -> Bool) -> c a -> c a
    filter = reduce . filtering

    instance Category Transducer where
    id = MkTrans id
    MkTrans f . MkTrans g = MkTrans $ \x -> g (f x)

    dub :: Num a => a -> a
    dub x = x + x

    test1 :: [Int]
    test1 = reduce (filtering even . mapping dub) [1..10]
    -- [2,4,6,8,10,12,14,16,18,20]

    test2 :: [Int]
    test2 = reduce (mapping dub . filtering even) [1..10]
    -- [4,8,12,16,20]
    *Main> :t reduce . mapping
    reduce . mapping :: Collection c => (a -> b) -> c a -> c b

    您也可以查看 http://www.reddit.com/r/haskell/comments/2cv6l4/clojures_transducers_are_perverse_lenses/
    其中定义为 type Transducer a b =:: (a -> Constant (Endo x) a) -> (b -> Constant (Endo x) b)和其他各种。还有其他有趣的讨论。

    关于haskell - Haskell 中的换能器和单态性限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27887907/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com