如何使用Haskell中的foldr函数在无限列表中找到元素?

时间:2015-09-27 16:16:12

标签: haskell functional-programming find element fold

我尝试使用if(isset($_SERVER["Authorization"]) && $_SERVER["Authorization"] == '2d30ff242f8650954bfe8c993f084f4f'){ $checkApi = true; } 函数在Haskell中创建using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Threading.Tasks; /// <summary> /// Creates a GIF using .Net GIF encoding and additional animation headers. /// </summary> public class GifWriter : IDisposable { #region Fields const long SourceGlobalColorInfoPosition = 10, SourceImageBlockPosition = 789; readonly BinaryWriter _writer; bool _firstFrame = true; readonly object _syncLock = new object(); #endregion /// <summary> /// Creates a new instance of GifWriter. /// </summary> /// <param name="OutStream">The <see cref="Stream"/> to output the Gif to.</param> /// <param name="DefaultFrameDelay">Default Delay between consecutive frames... FrameRate = 1000 / DefaultFrameDelay.</param> /// <param name="Repeat">No of times the Gif should repeat... -1 to repeat indefinitely.</param> public GifWriter(Stream OutStream, int DefaultFrameDelay = 500, int Repeat = -1) { if (OutStream == null) throw new ArgumentNullException(nameof(OutStream)); if (DefaultFrameDelay <= 0) throw new ArgumentOutOfRangeException(nameof(DefaultFrameDelay)); if (Repeat < -1) throw new ArgumentOutOfRangeException(nameof(Repeat)); _writer = new BinaryWriter(OutStream); this.DefaultFrameDelay = DefaultFrameDelay; this.Repeat = Repeat; } /// <summary> /// Creates a new instance of GifWriter. /// </summary> /// <param name="FileName">The path to the file to output the Gif to.</param> /// <param name="DefaultFrameDelay">Default Delay between consecutive frames... FrameRate = 1000 / DefaultFrameDelay.</param> /// <param name="Repeat">No of times the Gif should repeat... -1 to repeat indefinitely.</param> public GifWriter(string FileName, int DefaultFrameDelay = 500, int Repeat = -1) : this(new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read), DefaultFrameDelay, Repeat) { } #region Properties /// <summary> /// Gets or Sets the Default Width of a Frame. Used when unspecified. /// </summary> public int DefaultWidth { get; set; } /// <summary> /// Gets or Sets the Default Height of a Frame. Used when unspecified. /// </summary> public int DefaultHeight { get; set; } /// <summary> /// Gets or Sets the Default Delay in Milliseconds. /// </summary> public int DefaultFrameDelay { get; set; } /// <summary> /// The Number of Times the Animation must repeat. /// -1 indicates no repeat. 0 indicates repeat indefinitely /// </summary> public int Repeat { get; } #endregion /// <summary> /// Adds a frame to this animation. /// </summary> /// <param name="Image">The image to add</param> /// <param name="Delay">Delay in Milliseconds between this and last frame... 0 = <see cref="DefaultFrameDelay"/></param> public void WriteFrame(Image Image, int Delay = 0) { lock (_syncLock) using (var gifStream = new MemoryStream()) { Image.Save(gifStream, ImageFormat.Gif); // Steal the global color table info if (_firstFrame) InitHeader(gifStream, _writer, Image.Width, Image.Height); WriteGraphicControlBlock(gifStream, _writer, Delay == 0 ? DefaultFrameDelay : Delay); WriteImageBlock(gifStream, _writer, !_firstFrame, 0, 0, Image.Width, Image.Height); } if (_firstFrame) _firstFrame = false; } #region Write void InitHeader(Stream SourceGif, BinaryWriter Writer, int Width, int Height) { // File Header Writer.Write("GIF".ToCharArray()); // File type Writer.Write("89a".ToCharArray()); // File Version Writer.Write((short)(DefaultWidth == 0 ? Width : DefaultWidth)); // Initial Logical Width Writer.Write((short)(DefaultHeight == 0 ? Height : DefaultHeight)); // Initial Logical Height SourceGif.Position = SourceGlobalColorInfoPosition; Writer.Write((byte)SourceGif.ReadByte()); // Global Color Table Info Writer.Write((byte)0); // Background Color Index Writer.Write((byte)0); // Pixel aspect ratio WriteColorTable(SourceGif, Writer); // App Extension Header for Repeating if (Repeat == -1) return; Writer.Write(unchecked((short)0xff21)); // Application Extension Block Identifier Writer.Write((byte)0x0b); // Application Block Size Writer.Write("NETSCAPE2.0".ToCharArray()); // Application Identifier Writer.Write((byte)3); // Application block length Writer.Write((byte)1); Writer.Write((short)Repeat); // Repeat count for images. Writer.Write((byte)0); // terminator } static void WriteColorTable(Stream SourceGif, BinaryWriter Writer) { SourceGif.Position = 13; // Locating the image color table var colorTable = new byte[768]; SourceGif.Read(colorTable, 0, colorTable.Length); Writer.Write(colorTable, 0, colorTable.Length); } static void WriteGraphicControlBlock(Stream SourceGif, BinaryWriter Writer, int FrameDelay) { SourceGif.Position = 781; // Locating the source GCE var blockhead = new byte[8]; SourceGif.Read(blockhead, 0, blockhead.Length); // Reading source GCE Writer.Write(unchecked((short)0xf921)); // Identifier Writer.Write((byte)0x04); // Block Size Writer.Write((byte)(blockhead[3] & 0xf7 | 0x08)); // Setting disposal flag Writer.Write((short)(FrameDelay / 10)); // Setting frame delay Writer.Write(blockhead[6]); // Transparent color index Writer.Write((byte)0); // Terminator } static void WriteImageBlock(Stream SourceGif, BinaryWriter Writer, bool IncludeColorTable, int X, int Y, int Width, int Height) { SourceGif.Position = SourceImageBlockPosition; // Locating the image block var header = new byte[11]; SourceGif.Read(header, 0, header.Length); Writer.Write(header[0]); // Separator Writer.Write((short)X); // Position X Writer.Write((short)Y); // Position Y Writer.Write((short)Width); // Width Writer.Write((short)Height); // Height if (IncludeColorTable) // If first frame, use global color table - else use local { SourceGif.Position = SourceGlobalColorInfoPosition; Writer.Write((byte)(SourceGif.ReadByte() & 0x3f | 0x80)); // Enabling local color table WriteColorTable(SourceGif, Writer); } else Writer.Write((byte)(header[9] & 0x07 | 0x07)); // Disabling local color table Writer.Write(header[10]); // LZW Min Code Size // Read/Write image data SourceGif.Position = SourceImageBlockPosition + header.Length; var dataLength = SourceGif.ReadByte(); while (dataLength > 0) { var imgData = new byte[dataLength]; SourceGif.Read(imgData, 0, dataLength); Writer.Write((byte)dataLength); Writer.Write(imgData, 0, dataLength); dataLength = SourceGif.ReadByte(); } Writer.Write((byte)0); // Terminator } #endregion /// <summary> /// Frees all resources used by this object. /// </summary> public void Dispose() { // Complete File _writer.Write((byte)0x3b); // File Trailer _writer.BaseStream.Dispose(); _writer.Dispose(); } } 函数的新实现。

到目前为止,我有这个:

elem

foldr函数使用count :: Eq a => a -> [a] -> Integer count x (y:ys) = foldl (\counter y -> if y == x then counter + 1 else counter) 0 ys count _ [] = 0 elem' :: Eq a => a -> [a] -> Bool elem' x (y:ys) = foldr (\i elem-> if (count x (y:ys)) > 0 then True else False) False ys elem' _ [] = False 计算x(我写的另一个函数)的出现次数。这适用于有限列表,但问题是我想利用无限列表的count惰性计算。如果我尝试使用无限列表作为输入,程序将永远挂起。

基本上我想&#34;突破&#34;一旦我在列表中找到x的任何实例并返回true,否则返回false。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

让我们从foldr模式的基本骨架开始:

elem :: Eq a => [a] -> Bool
elem x xs = foldr kons knil xs

foldr看到[]时,它会返回knil。由于什么都不是空列表的元素,我们得出结论

knil = False

foldr kons False看到列表a : as时,它会返回kons a (foldr kons False as)。我们可以归纳为foldr kons False as = elem x as,因此我们寻求在

中求解kons
elem x (a : as) = kons a (elem x as)

我打赌你可以通过提出kons的定义来完成。注意布尔短路行为,以提高效率并避免无限列表出现问题。