正确导入已在Haskell中的Prelude中定义的内容

mb1*_*b14 15 haskell coding-style

我正在尝试在Haskell中定义一个可折叠的实例,我在导入时遇到了一些问题.

所以先试试:模块MyList在哪里

import Data.Foldable

data MyList a = MyList [a]

instance Foldable (MyList) where
  foldr f b (MyList as) = foldr f b as
Run Code Online (Sandbox Code Playgroud)

结果(正常但很烦人)

模糊发生`foldr'

所以,我想我必须将它从Prelude:模块MyList中隐藏起来

import Prelude hiding (foldr)
import Data.Foldable

data MyList a = MyList [a]

instance Foldable (MyList) where
  foldr f b (MyList as) = foldr f b as
Run Code Online (Sandbox Code Playgroud)

这个编译,我加载到ghci并尝试一些基本的东西:

*MyList> foldr (:) "" (MyList "hello")
"hello"
*MyList> foldl (flip (:)) "" (MyList "hello")

<interactive>:1:0:
    Ambiguous occurrence `foldl'
    It could refer to either `Prelude.foldl', imported from Prelude at MyList.hs:4:0-28
                          or `Data.Foldable.foldl', imported from Data.Foldable at MyList.hs:5:0-19
*MyList>
Run Code Online (Sandbox Code Playgroud)

所以foldr有效,但foldl没有.我的第一个问题是

我是否必须手动隐藏Data.Foldable中定义的每个方法来自Prelude是一个很好的方法吗?

.

为了避免这个问题,我试着做一个合格的导入:模块MyList在哪里

import qualified  Data.Foldable as F

data MyList a = MyList [a]

instance F.Foldable (MyList) where
  foldr f b (MyList as) = foldr f b as
Run Code Online (Sandbox Code Playgroud)

似乎在ghc中编译但是

*MyList> foldr (:) "" (MyList "hello")

<interactive>:1:14:
    Couldn't match expected type `[Char]'
           against inferred type `MyList Char'
    In the third argument of `foldr', namely `(MyList "hello")'
    In the expression: foldr (:) "" (MyList "hello")
    In the definition of `it': it = foldr (:) "" (MyList "hello")
Run Code Online (Sandbox Code Playgroud)

找不到foldr,但令人惊讶的是F.foldr在ghci中工作.

*MyList> F.foldr (:) "" (MyList "hello")
"hello"
Run Code Online (Sandbox Code Playgroud)

但仅在ghci中,如果我正在尝试在文件中导入MyList,则foldr,F.foldr,MyList.F.foldr和MyList.foldr不起作用.

为什么它在ghci中有效但在实际中不起作用?

我想我必须再次导入Data.Foldable(并在使用MyList的每个文件中再次)

有没有更好的方法(如在MyList中导出Data.Foldable)?

(我是Haskell的新手,尤其是模块)


在做了几个回复后,似乎没有解决这个问题的干净方案.但是,我很确定我不是第一个那样做的,所以

处理这类问题的常见做法是什么?

谢谢你的帮助.

Sim*_*low 7

为什么它在ghci中有效但在实际中不起作用?

因为在GHCi会话中,您在MyList模块的上下文中键入了表达式,所以F.foldr在范围内,但是如果您导入MyList到另一个模块,那么只有导出的名称MyList和导入的其他模块在范围内.

你的猜测是正确的 - 在每个模块使用中Data.Foldable.foldr,你必须这样做

import qualified Data.Foldable as F
Run Code Online (Sandbox Code Playgroud)

模块导出的名称不合格; 在导入模块时决定是否限定这些名称.

多年来一直有建议允许出口合格的名称,但到目前为止还没有实施任何内容.


Ion*_*tan 6

关于隐式Prelude导入,您可以添加以下语言编译指示,然后显式导入内容Prelude,但它可能比简单地隐藏Prelude或使用合格的导入更加丑陋Data.Foldable.

{-# LANGUAGE NoImplicitPrelude #-}

import Prelude (someFunction)
Run Code Online (Sandbox Code Playgroud)

为什么它会变得更丑陋?因为您可能必须导入被认为是理所当然的数据类型和函数,或者甚至导入未在代码中明确使用的函数:

{-# LANGUAGE NoImplicitPrelude #-}
module Main (main) where

-- we import fromInteger although it's not explicitly used
import Prelude (Int, foldl, fromInteger, (+), putStrLn, (.), ($), IO, show)

sum :: [Int] -> Int
sum = foldl (+) 0

main :: IO ()
main = putStrLn . show $ sum [1,2,3]
Run Code Online (Sandbox Code Playgroud)

我告诉过你这不是因为这是一个很好的解决方案,而是知道有这样的事情.


Bla*_*ade 2

这是 Thomas Eding 解决方案的一个变体,打字量较少。基本上,你可以导入(在Prelude'中)隐藏一些功能的Prelude,然后重新导出Prelude;这将导出 Prelude 减去这些功能。这种技术对于编写仅重新导出库中的某些函数的前端模块通常很有用。

然后您也可以重新导出Data.Foldable

我用等效函数替换了一些 Prelude 函数(Foldable和 的示例Category)。

module Prelude2 (module Prelude, module Data.Foldable, module Control.Category) where

import Prelude hiding (id, (.), foldr)
import Data.Foldable (Foldable, foldr) -- You might want to import everything.
import Control.Category (Category((.), id))
-- Try out replacing with:
-- import Control.Category ()
-- to see that no (.) is available.
Run Code Online (Sandbox Code Playgroud)

用法:

module Foo where
import Prelude()
import Prelude2
Run Code Online (Sandbox Code Playgroud)

也就是说,请注意中foldr和 的类型,如 GHCi 所示:(.)Foo

$ ghci Foo.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 2] Compiling Prelude2         ( src-lib/Prelude2.hs, interpreted )
[2 of 2] Compiling Foo              ( /Users/pgiarrusso/AeroFS/Repos/pts-bluevelvet/src-lib/Foo.hs, interpreted )
Ok, modules loaded: Foo, Prelude2.
*Foo> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
*Foo> :t (.)
(.) :: Category cat => cat b c -> cat a b -> cat a c
*Foo>
Run Code Online (Sandbox Code Playgroud)

如果您尝试更换的建议

 import Control.Category ()
Run Code Online (Sandbox Code Playgroud)

GHCi 将向您展示(.)根本没有定义Foo

*Foo> :r
[1 of 2] Compiling Prelude2         ( src-lib/Prelude2.hs, interpreted )
[2 of 2] Compiling Foo              ( /Users/pgiarrusso/AeroFS/Repos/pts-bluevelvet/src-lib/Foo.hs, interpreted ) [Prelude2 changed]
Ok, modules loaded: Foo, Prelude2.
*Foo> :t (.)

<interactive>:1:1: Not in scope: `.'
Run Code Online (Sandbox Code Playgroud)